patternjavaMinor
Java JSON parsing with the Nashorn API
Viewed 0 times
thenashornwithjavaparsingjsonapi
Problem
Some time ago I found a website about the Java Nashorn API which allows you to run JavaScript from Java code. I thought about creating a JSON parser in pure Java (without external libraries) which makes use of this API and the JavaScript function
My goal is to make this parser as fast, resource efficient and easy as possible.
So I would like to know if the following code is efficient compared to JSON libraries and how I could improve it in terms of performance and accuracy.
Code
JSONFile.java
JSONObject.java
```
package com.example.json;
import java.util.Map;
public class JSONObject {
private Map map;
@SuppressWarnings("unchecked")
public JSONObject(Object object) {
map = (Map) object;
}
public Object get(String key) {
return map.get(key);
}
public String getString(String key) {
JSON.parse()My goal is to make this parser as fast, resource efficient and easy as possible.
So I would like to know if the following code is efficient compared to JSON libraries and how I could improve it in terms of performance and accuracy.
Code
JSONFile.java
package com.example.json;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class JSONFile {
public static final JSONObject parseFromPath(String path) {
return parseFromString(TextFile.readFromPath(path));
}
public static final JSONObject parseFromResource(String resource) {
return parseFromString(TextFile.readFromResource(resource));
}
public static final JSONObject parseFromURL(String url) {
return parseFromString(TextFile.readFromURL(url));
}
public static final JSONObject parseFromString(String json) {
try {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval(TextFile.readFromResource("/js/jsonparser.js"));
return new JSONObject(((Invocable) engine).invokeFunction("parseJSON", json));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ScriptException e) {
e.printStackTrace();
}
return null;
}
}JSONObject.java
```
package com.example.json;
import java.util.Map;
public class JSONObject {
private Map map;
@SuppressWarnings("unchecked")
public JSONObject(Object object) {
map = (Map) object;
}
public Object get(String key) {
return map.get(key);
}
public String getString(String key) {
Solution
Method names and argument types
A school of thought is that one can also use the argument type(s) to simplify the method names. In other words, if the method name says it is parsing from
An additional benefit of this is that you eliminate to risk of calling
Auto-boxing
You rely on auto-boxing for your
public static final JSONObject parseFromPath(String path) { ... }
public static final JSONObject parseFromResource(String resource) { ... }
public static final JSONObject parseFromURL(String url) { ... }
public static final JSONObject parseFromString(String json) { .. }A school of thought is that one can also use the argument type(s) to simplify the method names. In other words, if the method name says it is parsing from
Path, why not accept a Path object then?public static final JSONObject parse(Path path) { ... }
public static final JSONObject parse(InputStream resource) { ... }
public static final JSONObject parse(URL url) { ... }
public static final JSONObject parse(String json) { .. }An additional benefit of this is that you eliminate to risk of calling
parseFromString() accidentally, when the argument is really a URL. Auto-boxing
You rely on auto-boxing for your
JSONObject and JSONArray classes. The problem with this is that you get a nasty NullPointerException if there is no mapped/array value, and the JVM is trying to unbox the null to one of the primitive types. Also, if the value is not the desired primitive type wrapper object, you will get a ClassCastException too. You should consider checking for that, for example:public class JSONArray {
// ...
public int getInteger(int index) {
Object value = array[index];
if (value instanceof Integer) {
return (Integer) value;
}
throw new IllegalArgumentException("Non-integer value at array index: " + index);
}
}Code Snippets
public static final JSONObject parseFromPath(String path) { ... }
public static final JSONObject parseFromResource(String resource) { ... }
public static final JSONObject parseFromURL(String url) { ... }
public static final JSONObject parseFromString(String json) { .. }public static final JSONObject parse(Path path) { ... }
public static final JSONObject parse(InputStream resource) { ... }
public static final JSONObject parse(URL url) { ... }
public static final JSONObject parse(String json) { .. }public class JSONArray {
// ...
public int getInteger(int index) {
Object value = array[index];
if (value instanceof Integer) {
return (Integer) value;
}
throw new IllegalArgumentException("Non-integer value at array index: " + index);
}
}Context
StackExchange Code Review Q#90272, answer score: 5
Revisions (0)
No revisions yet.