diff --git a/pom.xml b/pom.xml
index 5b967ac..7199704 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,6 +7,18 @@
org.example
GGD
1.0-SNAPSHOT
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 7
+
+
+
+
org.apache.jena
@@ -25,6 +37,17 @@
jena-fuseki-main
3.16.0
+
+ info.picocli
+ picocli
+ 4.5.1
+
+
+ org.glassfish
+ javax.json
+ 1.1.4
+
+
diff --git a/src/main/java/Data/city-distances.json b/src/main/java/Data/city-distances.json
new file mode 100644
index 0000000..957f72d
--- /dev/null
+++ b/src/main/java/Data/city-distances.json
@@ -0,0 +1,28 @@
+{
+ "desc" : "Distances between several cities, in kilometers.",
+ "updated" : "2014-02-04T18:50:45",
+ "uptodate": true,
+ "author" : null,
+ "cities" : {
+ "Brussels": [
+ {"to": "London", "distance": 322},
+ {"to": "Paris", "distance": 265},
+ {"to": "Amsterdam", "distance": 173}
+ ],
+ "London": [
+ {"to": "Brussels", "distance": 322},
+ {"to": "Paris", "distance": 344},
+ {"to": "Amsterdam", "distance": 358}
+ ],
+ "Paris": [
+ {"to": "Brussels", "distance": 265},
+ {"to": "London", "distance": 344},
+ {"to": "Amsterdam", "distance": 431}
+ ],
+ "Amsterdam": [
+ {"to": "Brussels", "distance": 173},
+ {"to": "London", "distance": 358},
+ {"to": "Paris", "distance": 431}
+ ]
+ }
+}
diff --git a/src/main/java/JSON2RDF/JSON2RDF.java b/src/main/java/JSON2RDF/JSON2RDF.java
new file mode 100644
index 0000000..00022c2
--- /dev/null
+++ b/src/main/java/JSON2RDF/JSON2RDF.java
@@ -0,0 +1,67 @@
+package JSON2RDF;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.jena.riot.system.StreamRDF;
+import org.apache.jena.riot.system.StreamRDFLib;
+import picocli.CommandLine;
+
+@CommandLine.Command(name = "json2rdf")
+public class JSON2RDF {
+ private final InputStream jsonIn;
+ private final OutputStream rdfOut;
+
+ @CommandLine.Parameters(paramLabel = "base", index = "0", description = "Base URI of the RDF output data\nExample: https://localhost/")
+ private URI baseURI;
+
+ @CommandLine.Option(names = { "--input-charset" }, description = "Input charset (default: ${DEFAULT-VALUE})")
+ private Charset inputCharset = StandardCharsets.UTF_8;
+
+ @CommandLine.Option(names = { "--output-charset" }, description = "Output charset (default: ${DEFAULT-VALUE})")
+ private Charset outputCharset = StandardCharsets.UTF_8;
+
+ public static void main(String[] args) throws IOException
+ {
+ JSON2RDF json2rdf = new JSON2RDF(System.in, System.out);
+
+ try
+ {
+ CommandLine.ParseResult parseResult = new CommandLine(json2rdf).parseArgs(args);
+ if (!CommandLine.printHelpIfRequested(parseResult)) json2rdf.convert();
+ }
+ catch (CommandLine.ParameterException ex)
+ { // command line arguments could not be parsed
+ System.err.println(ex.getMessage());
+ ex.getCommandLine().usage(System.err);
+ }
+ }
+
+ public JSON2RDF(InputStream csvIn, OutputStream rdfOut)
+ {
+ this.jsonIn = csvIn;
+ this.rdfOut = rdfOut;
+ }
+
+ public void convert() throws IOException
+ {
+ if (jsonIn.available() == 0) throw new IllegalStateException("JSON input not provided");
+
+ try (Reader reader = new BufferedReader(new InputStreamReader(jsonIn, inputCharset)))
+ {
+ StreamRDF rdfStream = StreamRDFLib.writer(new BufferedWriter(new OutputStreamWriter(rdfOut, outputCharset)));
+ new JsonStreamRDFWriter(reader, rdfStream, baseURI.toString()).convert();
+ }
+ }
+
+}
+
diff --git a/src/main/java/JSON2RDF/JsonStreamRDFWriter.java b/src/main/java/JSON2RDF/JsonStreamRDFWriter.java
new file mode 100644
index 0000000..d75e8df
--- /dev/null
+++ b/src/main/java/JSON2RDF/JsonStreamRDFWriter.java
@@ -0,0 +1,124 @@
+package JSON2RDF;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
+import javax.json.Json;
+import javax.json.stream.JsonParser;
+import org.apache.jena.datatypes.xsd.XSDDatatype;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.graph.Triple;
+import org.apache.jena.riot.system.IRIResolver;
+import org.apache.jena.riot.system.StreamRDF;
+
+
+public class JsonStreamRDFWriter
+{
+
+ private final JsonParser parser;
+ private final StreamRDF rdfStream;
+ private final IRIResolver iriResolver;
+
+ public JsonStreamRDFWriter(Reader reader, StreamRDF rdfStream, String baseURI)
+ {
+ this(Json.createParser(reader), rdfStream, baseURI);
+ }
+
+ public JsonStreamRDFWriter(InputStream is, StreamRDF rdfStream, String baseURI)
+ {
+ this(Json.createParser(is), rdfStream, baseURI);
+ }
+
+ public JsonStreamRDFWriter(JsonParser parser, StreamRDF rdfStream, String baseURI)
+ {
+ this.parser = parser;
+ this.rdfStream = rdfStream;
+ this.iriResolver = IRIResolver.create(baseURI);
+ }
+
+ public void convert()
+ {
+ getStreamRDF().start();
+
+ write(getParser(), getStreamRDF(), getIRIResolver());
+
+ getStreamRDF().finish();
+ }
+
+ public static void write(JsonParser parser, StreamRDF rdfStream, IRIResolver iriResolver)
+ {
+ Deque subjectStack = new ArrayDeque<>();
+ Map arrayProperties = new HashMap<>();
+
+ Node property = null;
+ while (parser.hasNext())
+ {
+ JsonParser.Event event = parser.next();
+
+ switch (event)
+ {
+ case START_ARRAY:
+ if (!subjectStack.isEmpty() && property != null) arrayProperties.put(subjectStack.getLast(), property);
+ break;
+ case END_ARRAY:
+ if (!subjectStack.isEmpty()) arrayProperties.remove(subjectStack.getLast());
+ break;
+ case START_OBJECT:
+ Node subject = NodeFactory.createBlankNode();
+ // add triple with current array property, if any
+ if (property != null && !subjectStack.isEmpty()) rdfStream.triple(new Triple(subjectStack.getLast(), property, subject));
+ subjectStack.addLast(subject);
+ break;
+ case END_OBJECT:
+ subjectStack.removeLast();
+ // restore previous array property, if there was any
+ if (!subjectStack.isEmpty() && arrayProperties.containsKey(subjectStack.getLast())) property = arrayProperties.get(subjectStack.getLast());
+ break;
+ case VALUE_FALSE:
+ rdfStream.triple(new Triple(subjectStack.getLast(), property, NodeFactory.createLiteralByValue(Boolean.FALSE, XSDDatatype.XSDboolean)));
+ break;
+ case VALUE_TRUE:
+ rdfStream.triple(new Triple(subjectStack.getLast(), property, NodeFactory.createLiteralByValue(Boolean.TRUE, XSDDatatype.XSDboolean)));
+ break;
+ case KEY_NAME:
+ property = NodeFactory.createURI(iriResolver.resolveToString("#" + parser.getString()));
+ break;
+ case VALUE_STRING:
+ if (property != null) rdfStream.triple(new Triple(subjectStack.getLast(), property, NodeFactory.createLiteral(parser.getString())));
+ break;
+ case VALUE_NUMBER:
+ try
+ {
+ rdfStream.triple(new Triple(subjectStack.getLast(), property,NodeFactory.createLiteralByValue(Integer.valueOf(parser.getString()), XSDDatatype.XSDint)));
+ }
+ catch (NumberFormatException ex)
+ {
+ rdfStream.triple(new Triple(subjectStack.getLast(), property,NodeFactory.createLiteralByValue(Float.valueOf(parser.getString()), XSDDatatype.XSDfloat)));
+ }
+ break;
+ case VALUE_NULL:
+ break;
+ }
+ }
+ }
+
+ protected JsonParser getParser()
+ {
+ return parser;
+ }
+
+ protected StreamRDF getStreamRDF()
+ {
+ return rdfStream;
+ }
+
+ protected IRIResolver getIRIResolver()
+ {
+ return iriResolver;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/main.java b/src/main/java/main.java
index 1ec8312..6aa1378 100644
--- a/src/main/java/main.java
+++ b/src/main/java/main.java
@@ -1,4 +1,5 @@
+import JSON2RDF.JSON2RDF;
import org.apache.jena.rdf.model.*;
import org.apache.jena.vocabulary.*;
@@ -44,5 +45,6 @@ public class main {
System.out.println(" .");
}
}
+
}