Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

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.

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<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.java

package 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.java

package 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.js

function 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]"; }

Example

example.json (Source: http://www.w3schools.com/json/)

{"employees":[
    {"firstName":"John", "lastName":"Doe"},
    {"firstName":"Anna", "lastName":"Smith"},
    {"firstName":"Peter", "lastName":"Jones"}
]}

JSONTest.java

public 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"));
        }
    }

}

Result

Doe, John
Smith, Anna
Jones, Peter

I 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.

Thanks for helpful suggestions and comments to improve the code!

(If I have time in the next days, I'll probably make another example and add comments to the code)

share|improve this question

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.