Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added optional storage of constructor names and datatype names while serializing to JSON. Wired this through the different webservers as well #1862

Merged
merged 12 commits into from
Nov 25, 2024
Merged
Next Next commit
added optional storage of constructor names and datatype names while …
…serializing to JSON. Wired this through the different webservers as well
  • Loading branch information
jurgenvinju committed Sep 12, 2023
commit d860cf0bccfab41c75f70d2b691941d5b6dae416
2 changes: 1 addition & 1 deletion src/org/rascalmpl/library/Content.rsc
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ which involves a handy, automatic, encoding of Rascal values into json values.
data Response
= response(Status status, str mimeType, map[str,str] header, str content)
| fileResponse(loc file, str mimeType, map[str,str] header)
| jsonResponse(Status status, map[str,str] header, value val, str dateTimeFormat = "yyyy-MM-dd\'T\'HH:mm:ss\'Z\'")
| jsonResponse(Status status, map[str,str] header, value val, str dateTimeFormat = "yyyy-MM-dd\'T\'HH:mm:ss\'Z\'", bool explicitConstructorNames=false, bool explicitDataTypes=false)
;


8 changes: 6 additions & 2 deletions src/org/rascalmpl/library/lang/json/IO.java
Original file line number Diff line number Diff line change
@@ -137,7 +137,7 @@ public IValue parseJSON(IValue type, IString src, IString dateTimeFormat, IBool
}
}

public void writeJSON(ISourceLocation loc, IValue value, IBool unpackedLocations, IString dateTimeFormat, IBool dateTimeAsInt, IInteger indent, IBool dropOrigins) {
public void writeJSON(ISourceLocation loc, IValue value, IBool unpackedLocations, IString dateTimeFormat, IBool dateTimeAsInt, IInteger indent, IBool dropOrigins, IBool explicitConstructorNames, IBool explicitDataTypes) {
try (JsonWriter out = new JsonWriter(new OutputStreamWriter(URIResolverRegistry.getInstance().getOutputStream(loc, false), Charset.forName("UTF8")))) {
if (indent.intValue() > 0) {
out.setIndent(" ".substring(0, indent.intValue() % 9));
@@ -148,13 +148,15 @@ public void writeJSON(ISourceLocation loc, IValue value, IBool unpackedLocations
.setDatesAsInt(dateTimeAsInt.getValue())
.setUnpackedLocations(unpackedLocations.getValue())
.setDropOrigins(dropOrigins.getValue())
.setExplicitConstructorNames(explicitConstructorNames.getValue())
.setExplicitDataTypes(explicitDataTypes.getValue())
.write(out, value);
} catch (IOException e) {
throw RuntimeExceptionFactory.io(values.string(e.getMessage()), null, null);
}
}

public IString asJSON(IValue value, IBool unpackedLocations, IString dateTimeFormat, IBool dateTimeAsInt, IInteger indent, IBool dropOrigins) {
public IString asJSON(IValue value, IBool unpackedLocations, IString dateTimeFormat, IBool dateTimeAsInt, IInteger indent, IBool dropOrigins, IBool explicitConstructorNames, IBool explicitDataTypes) {
StringWriter string = new StringWriter();

try (JsonWriter out = new JsonWriter(string)) {
@@ -166,6 +168,8 @@ public IString asJSON(IValue value, IBool unpackedLocations, IString dateTimeFor
.setDatesAsInt(dateTimeAsInt.getValue())
.setUnpackedLocations(unpackedLocations.getValue())
.setDropOrigins(dropOrigins.getValue())
.setExplicitConstructorNames(explicitConstructorNames.getValue())
.setExplicitDataTypes(explicitDataTypes.getValue())
.write(out, value);

return values.string(string.toString());
36 changes: 24 additions & 12 deletions src/org/rascalmpl/library/lang/json/IO.rsc
Original file line number Diff line number Diff line change
@@ -15,25 +15,20 @@
module lang::json::IO

@javaClass{org.rascalmpl.library.lang.json.IO}
@deprecated{
use writeJSON
}
@deprecated{use writeJSON}
public java str toJSON(value v);

@javaClass{org.rascalmpl.library.lang.json.IO}
@deprecated{
use asJSON
}
@deprecated{use asJSON}
public java str toJSON(value v, bool compact);

@javaClass{org.rascalmpl.library.lang.json.IO}
@deprecated{
use readJSON
}
@deprecated{use readJSON}
public java &T fromJSON(type[&T] typ, str src);

@javaClass{org.rascalmpl.library.lang.json.IO}
@synopsis{reads JSON values from a stream
@synopsis{reads JSON values from a stream}
@description{
In general the translation behaves as follows:
* Objects translate to map[str,value] by default, unless a node is expected (properties are then translated to keyword fields)
* Arrays translate to lists by default, or to a set if that is expected or a tuple if that is expected. Arrays may also be interpreted as constructors or nodes (see below)
@@ -52,7 +47,24 @@ In general the translation behaves as the same as for ((readJSON)).}
java &T parseJSON(type[&T] expected, str src, str dateTimeFormat = "yyyy-MM-dd\'T\'HH:mm:ssZZZZZ", bool lenient=false, bool trackOrigins=false);

@javaClass{org.rascalmpl.library.lang.json.IO}
java void writeJSON(loc target, value val, bool unpackedLocations=false, str dateTimeFormat="yyyy-MM-dd\'T\'HH:mm:ssZZZZZ", bool dateTimeAsInt=false, int indent=0, bool dropOrigins=true);
@synopsis{Serializes a value as a JSON string and stream it}
@description{
This function tries to map Rascal values to JSON values in a natural way.
In particular it tries to create a value that has the same number of recursive levels,
such that one constructor maps to one object. The serialization is typically _lossy_ since
JSON values by default do not explicitly encode the class or constructor while Rascal data types do.

If you need the names of constructors or data-types in your result, then use the parameters:
* `explicitConstructorNames=true` will store the name of every constructor in a field `_constructor`
* `explicitDataTypes=true` will store the name of the ADT in a field called `_type`

The `dateTimeFormat` parameter dictates how `datetime` values will be printed.

The `unpackedLocations` parameter will produce an object with many fields for every property of a `loc` value, but
if set to false a `loc` will be printed as a string.
}
java void writeJSON(loc target, value val, bool unpackedLocations=false, str dateTimeFormat="yyyy-MM-dd\'T\'HH:mm:ssZZZZZ", bool dateTimeAsInt=false, int indent=0, bool dropOrigins=true, bool explicitConstructorNames=false, bool explicitDataTypes=false);

@javaClass{org.rascalmpl.library.lang.json.IO}
java str asJSON(value val, bool unpackedLocations=false, str dateTimeFormat="yyyy-MM-dd\'T\'HH:mm:ssZZZZZ", bool dateTimeAsInt=false, int indent = 0, bool dropOrigins=true);
@synopsis{Serializes a value as a JSON string and stores it as a string}
java str asJSON(value val, bool unpackedLocations=false, str dateTimeFormat="yyyy-MM-dd\'T\'HH:mm:ssZZZZZ", bool dateTimeAsInt=false, int indent = 0, bool dropOrigins=true, bool explicitConstructorNames=false, bool explicitDataTypes=false);
23 changes: 23 additions & 0 deletions src/org/rascalmpl/library/lang/json/internal/JsonValueWriter.java
Original file line number Diff line number Diff line change
@@ -44,6 +44,8 @@ public class JsonValueWriter {
private boolean datesAsInts = true;
private boolean unpackedLocations = false;
private boolean dropOrigins = true;
private boolean explicitConstructorNames = false;
private boolean explicitDataTypes;

public JsonValueWriter() {
setCalendarFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
@@ -78,6 +80,16 @@ public JsonValueWriter setDropOrigins(boolean setting) {
return this;
}

public JsonValueWriter setExplicitConstructorNames(boolean setting) {
this.explicitConstructorNames = setting;
return this;
}

public JsonValueWriter setExplicitDataTypes(boolean setting) {
this.explicitDataTypes = setting;
return this;
}

public void write(JsonWriter out, IValue value) throws IOException {
value.accept(new IValueVisitor<Void, IOException>() {

@@ -229,6 +241,17 @@ public Void visitConstructor(IConstructor o) throws IOException {
}

out.beginObject();

if (explicitConstructorNames) {
out.name("_constructor");
out.value(o.getName());
}

if (explicitDataTypes) {
out.name("_type");
out.value(o.getType().getName());
}

int i = 0;
for (IValue arg : o) {
out.name(o.getConstructorType().getFieldName(i));
9 changes: 7 additions & 2 deletions src/org/rascalmpl/library/util/TermREPL.java
Original file line number Diff line number Diff line change
@@ -238,10 +238,15 @@ private void handleJSONResponse(Map<String, InputStream> output, IConstructor re

IValue dtf = kws.getParameter("dateTimeFormat");
IValue dai = kws.getParameter("dateTimeAsInt");

IValue ecn = kws.getParameter("explicitConstructorNames");
IValue edt = kws.getParameter("explicitDataTypes");

JsonValueWriter writer = new JsonValueWriter()
.setCalendarFormat(dtf != null ? ((IString) dtf).getValue() : "yyyy-MM-dd\'T\'HH:mm:ss\'Z\'")
.setDatesAsInt(dai != null ? ((IBool) dai).getValue() : true);
.setDatesAsInt(dai != null ? ((IBool) dai).getValue() : true)
.setExplicitConstructorNames(ecn != null ? ((IBool) ecn).getValue() : false)
.setExplicitDataTypes(edt != null ? ((IBool) edt).getValue() : false)
;

final ByteArrayOutputStream baos = new ByteArrayOutputStream();

7 changes: 6 additions & 1 deletion src/org/rascalmpl/library/util/Webserver.java
Original file line number Diff line number Diff line change
@@ -238,10 +238,15 @@ private Response translateJsonResponse(Method method, IConstructor cons) {

IValue dtf = kws.getParameter("dateTimeFormat");
IValue dai = kws.getParameter("dateTimeAsInt");
IValue ecn = kws.getParameter("explicitConstructorNames");
IValue edt = kws.getParameter("explicitDataTypes");

JsonValueWriter writer = new JsonValueWriter()
.setCalendarFormat(dtf != null ? ((IString) dtf).getValue() : "yyyy-MM-dd\'T\'HH:mm:ss\'Z\'")
.setDatesAsInt(dai != null ? ((IBool) dai).getValue() : true);
.setDatesAsInt(dai != null ? ((IBool) dai).getValue() : true)
.setExplicitConstructorNames(ecn != null ? ((IBool) ecn).getValue() : false)
.setExplicitDataTypes(edt != null ? ((IBool) edt).getValue() : false)
;

try {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
7 changes: 6 additions & 1 deletion src/org/rascalmpl/repl/REPLContentServer.java
Original file line number Diff line number Diff line change
@@ -135,10 +135,15 @@ private static Response translateJsonResponse(Method method, IConstructor cons)

IValue dtf = kws.getParameter("dateTimeFormat");
IValue dai = kws.getParameter("dateTimeAsInt");
IValue ecn = kws.getParameter("explicitConstructorNames");
IValue edt = kws.getParameter("explicitDataTypes");

JsonValueWriter writer = new JsonValueWriter()
.setCalendarFormat(dtf != null ? ((IString) dtf).getValue() : "yyyy-MM-dd\'T\'HH:mm:ss\'Z\'")
.setDatesAsInt(dai != null ? ((IBool) dai).getValue() : true);
.setDatesAsInt(dai != null ? ((IBool) dai).getValue() : true)
.setExplicitConstructorNames(ecn != null ? ((IBool) ecn).getValue() : false)
.setExplicitDataTypes(edt != null ? ((IBool) edt).getValue() : false)
;

try {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();