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 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.CodeJSONFile.javapackage 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.javapackage com.example.json;import java.util.Map;public class JSONObject {    private Map<String, Object> map;    @SuppressWarnings(unchecked)    public JSONObject(Object object) {        map = (Map<String, Object>) object;    }    public Object get(String key) {        return map.get(key);    }    public String getString(String key) {        return (String) map.get(key);    }    public boolean getBoolean(String key) {        return (boolean) map.get(key);    }    public int getInteger(String key) {        return (int) map.get(key);    }    public float getFloat(String key) {        return (float) map.get(key);    }    public JSONObject getObject(String key) {        return new JSONObject(map.get(key));    }    public JSONArray getArray(String key) {        return new JSONArray((Object[]) map.get(key));    }}JSONArray.javapackage com.example.json;public class JSONArray {    private Object[] array;    public JSONArray(Object[] array) {        this.array = array;    }    public int length() {        return array.length;    }    public Object get(int index) {        return array[index];    }    public String getString(int index) {        return (String) array[index];    }    public boolean getBoolean(int index) {        return (boolean) array[index];    }    public int getInteger(int index) {        return (int) array[index];    }    public float getFloat(int index) {        return (float) array[index];    }    public JSONObject getObject(int index) {        return new JSONObject(array[index]);    }    public JSONArray getArray(int index) {        return new JSONArray((Object[]) array[index]);    }}TextFile.javapackage com.example.json;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.MalformedURLException;import java.net.URL;import java.nio.file.Files;import java.nio.file.Paths;import java.nio.file.StandardOpenOption;public class TextFile {    public static final String LINE_SEPARATOR = System.getProperty(line.separator);    public static final String readFromPath(String path) {        try {            return read(Files.newInputStream(Paths.get(path), StandardOpenOption.READ));        } catch (IOException e) {            e.printStackTrace();        }        return null;    }    public static final String readFromResource(String resource) {        return read(TextFile.class.getResourceAsStream(resource));    }    public static final String readFromURL(String url) {        try {            return read(new URL(url).openStream());        } catch (MalformedURLException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }        return null;    }    private static final String read(InputStream is) {        try {            BufferedReader reader = new BufferedReader(new InputStreamReader(is));            StringBuilder builder = new StringBuilder();            String line = null;            while ((line = reader.readLine()) != null) builder.append(line + LINE_SEPARATOR);            reader.close();            System.gc();            return builder.toString().trim();        } catch (IOException e) {            e.printStackTrace();        }        return null;    }}/js/sonparser.jsfunction parseJSON(json) { return convert(JSON.parse(json)); }function convert(object) {    if (isObject(object)) return toHashMap(object);    if (isArray(object)) return toArray(object);    return object;}function toHashMap(object) {    var map = new java.util.HashMap();    for (key in object) map.put(key, convert(object[key]));    return map;}function toArray(object) {    var array = Java.to(object, java.lang.Object[]);    for (var index = 0, len = array.length; index < len; index++) array[index] = convert(array[index]);    return array;}function isObject(object) { return Object.prototype.toString.call(object) === [object Object]; }function isArray(object) { return Object.prototype.toString.call(object) === [object Array]; }Exampleexample.json (Source: http://www.w3schools.com/json/){employees:[    {firstName:John, lastName:Doe},    {firstName:Anna, lastName:Smith},    {firstName:Peter, lastName:Jones}]}JSONTest.javapublic class JSONTest {    public static void main(String[] args) {        JSONArray employees = JSONFile.parseFromResource(/json/example.json).getArray(employees);        for (int index = 0, len = employees.length(); index < len; index++) {            JSONObject employee = employees.getObject(index);            System.out.println(employee.getString(lastName) + ,  + employee.getString(firstName));        }    }}ResultDoe, JohnSmith, AnnaJones, PeterI made some heavy changes to the code since the last edit. (Added JSONObject.java & JSONArray.java & TextFile.java and small improvements to JSONFile.java) So now it is much easier to use the code, as seen in the example.
Java JSON parsing with the Nashorn API
java;javascript;json
Method names and argument typespublic 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-boxingYou 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);    }}