Skip to content

Commit

Permalink
added optional storage of constructor names and datatype names while …
Browse files Browse the repository at this point in the history
…serializing to JSON. Wired this through the different webservers as well
  • Loading branch information
jurgenvinju committed Sep 12, 2023
1 parent d55cb74 commit d860cf0
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/org/rascalmpl/library/Content.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
;


Expand Down
8 changes: 6 additions & 2 deletions src/org/rascalmpl/library/lang/json/IO.java
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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)) {
Expand All @@ -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());
Expand Down
36 changes: 24 additions & 12 deletions src/org/rascalmpl/library/lang/json/IO.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Up @@ -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'");
Expand Down Expand Up @@ -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>() {

Expand Down Expand Up @@ -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));
Expand Down
9 changes: 7 additions & 2 deletions src/org/rascalmpl/library/util/TermREPL.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
7 changes: 6 additions & 1 deletion src/org/rascalmpl/library/util/Webserver.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
7 changes: 6 additions & 1 deletion src/org/rascalmpl/repl/REPLContentServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit d860cf0

Please sign in to comment.