Skip to content

Commit

Permalink
we need to be able to parse json from string values directly sometimes
Browse files Browse the repository at this point in the history
  • Loading branch information
jurgenvinju committed Sep 15, 2017
1 parent 19ceecd commit c0473ad
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/org/rascalmpl/library/lang/json/IO.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.nio.charset.Charset;

import org.rascalmpl.interpreter.IEvaluatorContext;
Expand Down Expand Up @@ -96,6 +97,25 @@ public IValue readJSON(IValue type, ISourceLocation loc, IBool implicitConstruct
}
}

public IValue parseJSON(IValue type, IString src, IBool implicitConstructors, IBool implicitNodes, IString dateTimeFormat) {
TypeStore store = new TypeStore();
Type start = new TypeReifier(values).valueToType((IConstructor) type, store);

try (JsonReader in = new JsonReader(new StringReader(src.getValue()))) {
return new JsonValueReader(values, store)
.setConstructorsAsObjects(implicitConstructors.getValue())
.setNodesAsObjects(implicitNodes.getValue())
.setCalendarFormat(dateTimeFormat.getValue())
.read(in, start);
}
catch (IOException e) {
throw RuntimeExceptionFactory.io(values.string(e.getMessage()), null, null);
}
catch (NullPointerException e) {
throw RuntimeExceptionFactory.io(values.string("NPE"), null, null);
}
}

public void writeJSON(ISourceLocation loc, IValue value, IBool implicitConstructors, IBool implicitNodes, IString dateTimeFormat, IBool dateTimeAsInt) {
try (JsonWriter out = new JsonWriter(new OutputStreamWriter(URIResolverRegistry.getInstance().getOutputStream(loc, false), Charset.forName("UTF8")))) {
new JsonValueWriter()
Expand Down
30 changes: 30 additions & 0 deletions src/org/rascalmpl/library/lang/json/IO.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,36 @@ A similar distinction is made for values of type `node`, configured using the `i
}
java &T readJSON(type[&T] expected, loc src, bool implicitConstructors = true, bool implicitNodes = true, str dateTimeFormat = "yyyy-MM-dd\'T\'HH:mm:ss\'Z\'");

@javaClass{org.rascalmpl.library.lang.json.IO}
@doc{parses JSON values from a string
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)
* Booleans translate to bools
* If the expected type provided is a datetime then an int instant is mapped and if a string is found then the dateTimeFormat parameter will be used to configure the parsing of a date-time string
* If the expected type provided is an ADT then this reader will map Json objects in a particular way, as configured by the implicitNodes and implicitConstructor
parameters.
* If num, int, real or rat are expected both strings and number values are mapped
* If loc is expected than strings which look like URI are parsed (containing :/) or a file:/// URI is build, or if an object is found each separate field of
a location object is read from the respective properties: { scheme : str, authority: str?, path: str?, fragment: str?, query: str?, offset: int, length: int, begin: [bl, bc], end: [el, ec]}

In "implicitConstructor" mode the name of a property will be used as the name of the nested constructor. So this expects data definitions to line up constructor
names with field names: `data MyType = myConstructor(MyType2 myConstructor2); data MyType2 = myConstructor2(int i)`
^_______________________________^

This would then map the Json input `"myConstructor" : { myConstructor2 : { "i" : 1 } }` to the Rascal value `myConstructor(myConstructor2(1))`

In this mode field names for keyword parameters map to keyword parameters and field names to positional parameters map to positional parameters (which do not have
to be printed in order in the Json input file).

In explicit constructor mode (`implicitConstructor==false`) the following array-based encoding is expected for constructor trees, by example:
`[ "myConstructor", [ ["myConstructor2", [ 1 ] ] ] ]` and when there are keyword parameters we allow a third field of the array which is an object mapping
Json properties to Rascal keyword fields.

A similar distinction is made for values of type `node`, configured using the `implicitNode` parameter.
}
java &T parseJSON(type[&T] expected, str src, bool implicitConstructors = true, bool implicitNodes = true, str dateTimeFormat = "yyyy-MM-dd\'T\'HH:mm:ss\'Z\'");

@javaClass{org.rascalmpl.library.lang.json.IO}
java void writeJSON(loc target, value val, bool implicitConstructors=true, bool implicitNodes=true, str dateTimeFormat="yyyy-MM-dd\'T\'HH:mm:ss\'Z\'", bool dateTimeAsInt=false);

0 comments on commit c0473ad

Please sign in to comment.