Sunday, June 2, 2024

How to convert JSON to Map in Java 8 without using third party libraries like Jackson or Gson

Hello guys, If you are working with JSON data then you may know that JSON is collection of key value pairs and that's why many times, you also need to convert them into a Map in Java. While there are many Java libraries like Jackson and Gson which provides support of parsing JSON to Java objects, there is not much support for JSON parsing or manipulation on standard JDK. While JSON parsing is still a long overdue, starting with JDK 8u60+ the built-in Nashorn engine is capable to convert JSON content into java.util.Map. No external dependencies are required for parsing JSON in to Map as you will learn in this article. 


Here is our sample JSON which we will use in our example for parsing:

{
  "user": {
    "id": 123,
    "name": "John Doe",
    "email": "john.doe@example.com",
    "address": {
      "street": "123 Main St",
      "city": "Anytown",
      "state": "CA",
      "zip": "12345"
    }
  },
  "todos": [
    {
      "id": 1,
      "title": "Buy groceries",
      "completed": false
    },
    {
      "id": 2,
      "title": "Call mom",
      "completed": true
    },
    {
      "id": 3,
      "title": "Finish project",
      "completed": false
    }
  ]
}

This JSON holds two keys users and todos and their value is user object and and an array of TODO items with an id, title and a status boolean flag called completed. 

For testing purpose either you can store this JSON string as .json file in your file system or you can paste is as it is in  a String variable. 

How to convert JSON to Map in Java 8 without using third party libraries like Jackson or Gson



Java Program to convert JSON to Map without using third party library

Here is the complete program to parse JSON and create a Map with the key an value pairs retrieved from JSON without using any third party libraries like Jackson or Gson.  This code make use of Nashorn JavaScript engine which comes with JDK 8. 

import java.io.IOException;
import java.util.Map;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;

public class JSONParsingTest {

    private ScriptEngine engine;
    private final String jsonSample = """
    {
      "user": {
        "id": 123,
        "name": "John Doe",
        "email": "john.doe@example.com",
        "address": {
          "street": "123 Main St",
          "city": "Anytown",
          "state": "CA",
          "zip": "12345"
        }
      },
      "todos": [
        {
          "id": 1,
          "title": "Buy groceries",
          "completed": false
        },
        {
          "id": 2,
          "title": "Call mom",
          "completed": true
        },
        {
          "id": 3,
          "title": "Finish project",
          "completed": false
        }
      ]
    }
    """;

    @Before
    public void initEngine() {
        ScriptEngineManager sem = new ScriptEngineManager();
        this.engine = sem.getEngineByName("javascript");
    }

    @Test
    public void parseJson() throws IOException, ScriptException {
        String json = jsonSample;
        String script = "Java.asJSONCompatible(" + json + ")";
        Object result = this.engine.eval(script);
        assertThat(result, instanceOf(Map.class));
        Map contents = (Map) result;
        contents.forEach((t, u) -> {
            System.out.println(t + ": " + u);
        });
    }
}


In this program, I have also used text block feature of Java 11 to neatly pack JSON inside a multiple line string without escaping. Without that writing JSON in Java is very tedious and messy and hardly readable. 

When you run the program, it will print the content of map as key value pair as shown below:

user: {id=123, name=John Doe, email=john.doe@example.com, 
address={street=123 Main St, city=Anytown, state=CA, zip=12345}}
todos: [{id=1, title=Buy groceries, completed=false}, 
{id=2, title=Call mom, completed=true}, 
{id=3, title=Finish project, completed=false}]


That's all It's cute and good to know that something like this is possible in Java 8, but I won't advise you to start a JavaScript engine just to parse a simple JSON String, Jackson and Gson are much better library and tried and tested.

Though, using the Nashorn JavaScript engine to convert JSON in Java, as demonstrated in the provided code, is a unique but somewhat unconventional approach. Most importantly because  Nashorn JavaScript engine was deprecated in JDK 11 and removed in JDK 15. This means that using this approach is not future-proof, and relying on it for new projects is not advisable


No comments:

Post a Comment

Feel free to comment, ask questions if you have any doubt.