How and how to parse Json in Java?


There is often a need to work with Json, in particular its reading and parsing. In Java, you usually know what type of variables you are working with, but when parsing Json, it is confusing that the type of fields can be any.

What are the ways to parse Json? How do I do this?

Here, for example, how to get data from Json, presented below?

{
    "firstName": "Json",
    "lastName": "Smith",
    "age": 30,
    "address": {
        "streetAddress": "666 1nd Street",
        "city": "New York",
        "state": "NY",
        "postalCode": 10021
    },
    "phoneNumbers": [
        {
            "type": "home",
            "number": "542 666-1234"
        },
        {
            "type": "fax",
            "number": "653 666-4567" 
        }
    ],
    "friends": [
        {
            "firstName": "Test",
            "lastName": "Snow",
            "age": 20,
            "phoneNumbers": [
                {
                    "type": "home",
                    "number": "141 111-1234"
                }
            ],
            "friends": [
                {
                    "firstName": "UnknownFirstName",
                    "lastName": "UnknownLastName",
                    "age": 999,
                    "phoneNumbers": [
                        {
                            "type": "home",
                            "number": "000 000-0000"
                        }
                    ]
                }
            ]
        },
        {
            "firstName": "Flash",
            "lastName": "Tompson",
            "age": 23,
            "phoneNumbers": [
                {
                    "type": "home",
                    "number": "999 111-1234"
                }
            ]
        }
    ]
}
Author: αλεχολυτ, 2017-11-15

4 answers

There are different ways to get the data, and of course, it depends on the tasks. I will try to consider some options for parsing Json.

Note: for each of the examples for parsing, Json will be taken from the question, so as not to copy in vain in the answer.


Simple Json

Where to get it: here / repository on github / or via Maven, etc.

This is the most primitive way. In fact, all that is here is JSONObject and JSONArray.

  • JSONArray can include several objects JSONObject, it can be traversed by a loop at each iteration to get an object JSONObject.
  • JSONObject - an object from which you can get its individual properties.

I would use it for small Json strings, where you don't have to bother too much, or if you are not too lazy to write your own handler class based on the code that is demonstrated below:

// Считываем json
Object obj = new JSONParser().parse(jsonString); // Object obj = new JSONParser().parse(new FileReader("JSONExample.json"));
// Кастим obj в JSONObject
JSONObject jo = (JSONObject) obj;
// Достаём firstName and lastName
String firstName = (String) jo.get("firstName"); 
String lastName = (String) jo.get("lastName");
System.out.println("fio: " + firstName + " " + lastName);
// Достаем массив номеров
JSONArray phoneNumbersArr = (JSONArray) jo.get("phoneNumbers");
Iterator phonesItr = phoneNumbersArr.iterator();
System.out.println("phoneNumbers:");
// Выводим в цикле данные массива
while (phonesItr.hasNext()) {
    JSONObject test = (JSONObject) phonesItr.next();
    System.out.println("- type: " + test.get("type") + ", phone: " + test.get("number"));
}

The rest of the work with nested arrays is similar. You can add them to List, Map, etc.


GSON

Where to get it: here / repository on github / or via Maven, etc.

Documentation: http://www.studytrails.com/java/json/java-google-json-introduction/

Allows parsing Json in the same way as Json-simple, i.e. using JSONObject and JSONArray (see documentation), but has a more powerful parsing tool. It is enough to create classes that repeat the Json structure. For parsing Json from the question, create classes:

class Person {
    public String firstName;
    public String lastName;
    public int age;
    public Address address;
    public List<Phones> phoneNumbers;
    public List<Person> friends;
}

class Address {
    public String streetAddress;
    public String city;
    public String state;
    public int postalCode;
}

class Phones {
    public String type;
    public String number;
}

Now it is enough to write:

Gson g = new Gson();
Person person = g.fromJson(jsonString, Person.class);

Everything! Magic! A miracle! Now in person there is an object with the type Person, which contains data with exactly the types that were specified in the created classes! Now you can work with any type, as it is used to always do: String, Integer, List, Map, and everything else.

// Выведет фамилии всех друзей с их телефонами
for (Person friend : person.friends) {
    System.out.print(friend.lastName);
    for (Phones phone : friend.phoneNumbers) {
        System.out.println(" - phone type: " + phone.type + ", phone number : " + phone.number);
    }
}

// output:
// Snow - phone type: home, phone number : 141 111-1234
// Tompson - phone type: home, phone number : 999 111-1234


Example of parsing in Map:

...... JSON for parsing:

{  
	"2":{  
		"sessions":[  
			{  
				"time":"13:00",
				"price":"410"
			},
			{  
				"time":"06:40",
				"price":"340"
			},
			{  
				"time":"16:50",
				"price":"370"
			}
		],
		"name":"Кинокис-L",
		"locate":"Москва, Садовая-Спасская ул., 21, 56",
		"metro":"Красные ворота"
	},
	"7":{  
		"sessions":[  
			{  
				"time":"06:35",
				"price":"190"
			},
			{  
				"time":"00:05",
				"price":"410"
			}
		],
		"name":"Кинокис-V",
		"locate":"Павелецкая пл., 2, строение 1",
		"metro":"Павелецкая"
	},
	"8":{  
		"sessions":[  
			{  
				"time":"15:10",
				"price":"330"
			}
		],
		"name":"Кинокис-J",
		"locate":"ул. Пречистенка, 40/2",
		"metro":"Кропоткинская"
	},
	"9":{  
		"sessions":[  
			{  
				"time":"13:00",
				"price":"600"
			},
			{  
				"time":"08:30",
				"price":"300"
			},
			{  
				"time":"04:00",
				"price":"510"
			},
			{  
				"time":"13:15",
				"price":"340"
			}
		],
		"name":"Кинокис-U",
		"locate":"Шарикоподшипниковская ул., 24",
		"metro":"Дубровка"
	}
}

...... Classes (POJO):

class Seanse {
    public String name;
    public String locate
    public String metro;
    public List<Sessions> sessions;
}

class Sessions {
    public String time;
    public double price;
}   

...... The analysis itself looks like this:

Gson g = new Gson();
Type type = new TypeToken<Map<String, Seanse>>(){}.getType();
Map<String, Seanse> myMap = g.fromJson(json, type);

Everything.

Additionally, in GSON, you can use annotations, for example: exclude the specified fields when parsing, change the variable name (for example, do not personFirstName, and fName) and much more. For more information, see the documentation .


Jackson

Where to get it: here / repository on github / or via Maven, etc.

Documentation and examples: https://github.com/FasterXML/jackson-docs

Like GSON, it also allows you to work using JSONObject and JSONArray if required, and it also knows how to parse based on the provided data. classes (see the example below).

Similarly, it can specify additional requirements through annotations, for example: do not parse the specified fields, use a custom class constructor, change the variable name (for example, not firstName, but fName), and much more. For more information, see the documentation .

ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue(jsonString, Person.class);

System.out.println("My fio: " + person.firstName + " " + person.lastName + " and my friends are: ");
for (Person friend : person.friends) {
    System.out.print(friend.lastName);
    for (Phones phone : friend.phoneNumbers) {
        System.out.println(" - phone type: " + phone.type + ", phone number : " + phone.number);
    }
}

// output:
// My fio: Json Smith and my friends are: 
// Snow - phone type: home, phone number : 141 111-1234
// Tompson - phone type: home, phone number : 999 111-1234

JsonPath

Where to get: via Maven and other collectors / github repository

Applies to so called XPath libraries. Its essence is similar to xpath in xml, that is, it is easy to get part of information from json ' a, at the specified path. It also allows you to filter by condition.

// Выведет все фамилии друзей
List<String> friendsLastnames = JsonPath.read(jsonString, "$.friends[*].lastName");
for (String lastname : friendsLastnames) {
    System.out.println(lastname);
}

// output:
// Snow
// Tompson

Example with a selection by condition:

// Поиск друга, которому больше 22 лет
List<String> friendsWithAges = JsonPath
.using(Configuration.defaultConfiguration())
.parse(jsonString)
.read("$.friends[?(@.age > 22)].lastName", List.class);

for (String lastname : friendsWithAges) {
    System.out.println(lastname);
}

// output:  
// Tompson
 47
Author: Алексей Шиманский, 2017-12-26 11:11:33

A few more options


LoganSquare

LoganSquare - based on Jackson ' s streaming API. By demonstrated tests works faster than GSON and Jackson. Therefore, it is good for Android.

Where to get it: repository on github / or via Maven / Gradle, etc.

Using: https://github.com/bluelinelabs/LoganSquare#usage

A simple example:

@JsonObject
public class Person {
    @JsonField(name="firstName")
    public String firstName;
    @JsonField(name="age")
    public int age;

    public void say() {
        System.out.println();
        System.out.println("My name is " + firstName + " , I'm " + age + " years old!");
    }
}

Parsing:

String jsonString = "{\"age\":15,\"firstName\":\"Adam\"}";
Person person = LoganSquare.parse(jsonString, Person.class);
person.say(); // My name is Adam , I'm 18 years old!

Moshi

Moshi is a modern JSON library for Android and Java.

Is good, according to the developers, for working with Android.

Where to get it: repository on github / or via Maven / Gradle, etc.

  • Example of parsing Json strings into an object Person:

    Moshi moshi = new Moshi.Builder().build();
    JsonAdapter<Person> jsonAdapter = moshi.adapter(Person.class);
    Person person = jsonAdapter.fromJson(jsonStringPerson);  // В person будут все данные
    
  • Example of parsing in Map:

    class Seanse {
        public String name;
        public String locate
        public String metro;
        public List<Sessions> sessions;
    }
    
    class Sessions {
        public String time;
        public double price;
    }
    
    public class Main {
        public static void main(String[] args) throws IOException { 
            String jsonStringForMap = "{\"2\":{\"sessions\":[{\"time\":\"13:00\",\"price\":\"410\"},{ \"time\":\"06:40\",\"price\":\"340\"},{  \"time\":\"16:50\",\"price\":\"370\"}],\"name\":\"Кинокис-L\",\"locate\":\"Москва, Садовая-Спасская ул., 21, 56\",\"metro\":\"Красные ворота\"},\"7\":{  \"sessions\":[  {  \"time\":\"06:35\",\"price\":\"190\"},{  \"time\":\"00:05\",\"price\":\"410\"}],\"name\":\"Кинокис-V\",\"locate\":\"Павелецкая пл., 2, строение 1\",\"metro\":\"Павелецкая\"},\"8\":{  \"sessions\":[  {  \"time\":\"15:10\",\"price\":\"330\"}],\"name\":\"Кинокис-J\",\"locate\":\"ул. Пречистенка, 40/2\",\"metro\":\"Кропоткинская\"},\"9\":{  \"sessions\":[  {  \"time\":\"13:00\",\"price\":\"600\"},{  \"time\":\"08:30\",\"price\":\"300\"},{  \"time\":\"04:00\",\"price\":\"510\"},{  \"time\":\"13:15\",\"price\":\"340\"}],\"name\":\"Кинокис-U\",\"locate\":\"Шарикоподшипниковская ул., 24\",\"metro\":\"Дубровка\"}}";
    
            Moshi moshi = new Moshi.Builder().build();
            Type map = Types.newParameterizedType(Map.class, String.class, Seanse.class);
            JsonAdapter<Map<String, Seanse>> jsonAdapter = moshi.adapter(map);
            Map<String, Seanse> seanseMap = jsonAdapter.fromJson(jsonStringForMap);
        }
    }
    

Genson

Where to get it: here / repository on github / or via Maven, etc.

Documentation: http://owlike.github.io/genson/Documentation/UserGuide/

By creating POJO (classes are created that repeat the structure of Json ' a) - an object is parsed from a string, pushing it into the necessary fields of objects. It is possible to filter properties, include or exclude fields when parsing, rename, ability to work with annotations etc. For more information, see the documentation.

  • Simple parsing:

    Genson genson = new Genson();
    Person person = genson.deserialize(jsonString, Person.class); // В person будут все данные
    
  • Parsing to a list:

    List<Object> persons = genson.deserialize("[{\"age\":28,\"name\":\"Foo\"}, {\"age\":30,\"name\":\"Bar\"}]", List.class);    
    // persons - список с данными объектов
    
  • Example of parsing in Map:

...... JSON for parsing:

{  
	"2":{  
		"sessions":[  
			{  
				"time":"13:00",
				"price":"410"
			},
			{  
				"time":"06:40",
				"price":"340"
			},
			{  
				"time":"16:50",
				"price":"370"
			}
		],
		"name":"Кинокис-L",
		"locate":"Москва, Садовая-Спасская ул., 21, 56",
		"metro":"Красные ворота"
	},
	"7":{  
		"sessions":[  
			{  
				"time":"06:35",
				"price":"190"
			},
			{  
				"time":"00:05",
				"price":"410"
			}
		],
		"name":"Кинокис-V",
		"locate":"Павелецкая пл., 2, строение 1",
		"metro":"Павелецкая"
	},
	"8":{  
		"sessions":[  
			{  
				"time":"15:10",
				"price":"330"
			}
		],
		"name":"Кинокис-J",
		"locate":"ул. Пречистенка, 40/2",
		"metro":"Кропоткинская"
	},
	"9":{  
		"sessions":[  
			{  
				"time":"13:00",
				"price":"600"
			},
			{  
				"time":"08:30",
				"price":"300"
			},
			{  
				"time":"04:00",
				"price":"510"
			},
			{  
				"time":"13:15",
				"price":"340"
			}
		],
		"name":"Кинокис-U",
		"locate":"Шарикоподшипниковская ул., 24",
		"metro":"Дубровка"
	}
}

...... Classes (POJO):

class Seanse {
    public String name;
    public String locate
    public String metro;
    public List<Sessions> sessions;
}

class Sessions {
    public String time;
    public double price;
}   

...... Parsing itself:

String jsonStringForMap = "ТУТ JSON СТРОКА, ОПИСАННАЯ ВЫШЕ";
Genson genson = new Genson();
Map<String, Seanse> seansesMap = genson.deserialize(jsonStringForMap, Map.class);

FastJson

Where to get it: via Maven and other collectors / repository on github. Directly description of working with xpath. Caution, profanity is Chinese.

Refers to XPath analogs.

The usual way:

Person person = JSON.parseObject(jsonString, Person.class);
int age = person.age;
System.out.println(age); // 30

Using XPpath

// Выведет все фамилии друзей
List<String> friendsLastnames = (List<String>) JSONPath.eval(person, "$.friends.lastName");
for (String lastname : friendsLastnames) {
    System.out.println(lastname);  // Snow  Tompson
}

// Поиск друга, которому больше 22 лет
List<String> friendsWithAges = (List<String>) JSONPath.eval(person, "$.friends[?(@.age > 22)].lastName");
for (String lastname : friendsWithAges) {
    System.out.println(lastname); // Tompson
}
 6
Author: Алексей Шиманский, 2017-12-28 11:56:36

JSON-P

Supports JSON serialization and parsing without pre-mapping in classes:

Maven:

<dependency>
    <groupId>javax.json</groupId>
    <artifactId>javax.json-api</artifactId>
    <version>1.1.2</version>
</dependency>
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.json</artifactId>
    <version>1.1.2</version>
</dependency>

Example of parsing a JSON string:

public static void main(String[] args) throws IOException {
    JsonReader reader = Json.createReader(new StringReader(jsonString));
    JsonObject jsonObject = reader.readObject();
}

Example of output of an object to a JSON string:

public static void main(String[] args) throws IOException {
    System.out.println(prettyPrintJson(jsonObject, 0));
}

public static String prettyPrintJson(JsonObject jsonObject, int indent) {

    String indentStr = getIndentStr(indent);
    String prettyJson = indentStr + "{";

    for (String key : jsonObject.keySet()) {
        prettyJson += "\n";
        prettyJson += indentStr + "  \"" + key + "\": ";
        try {
            JsonArray jsonArray = jsonObject.get(key).asJsonArray();
            prettyJson += "\n" + indentStr + "  [";
            for (JsonValue element : jsonArray) {
                prettyJson += "\n" + prettyPrintJson(element.asJsonObject(), indent + 4);
                prettyJson += ",";
            }
            prettyJson = prettyJson.substring(0, prettyJson.length() - 1);
            prettyJson += "\n" + indentStr + "  ]";
        } catch (Exception e) {
            try {
                prettyJson += "\n" + prettyPrintJson(jsonObject.get(key).asJsonObject(), indent + 2);
            } catch (Exception ee) {
                prettyJson += jsonObject.get(key).toString();
            }
        }
        prettyJson += ",";
    }
    prettyJson = prettyJson.substring(0, prettyJson.length() - 1);
    prettyJson += "\n" + indentStr + "}";
    return prettyJson;
}

public static String getIndentStr(int indent) {
    String indentStr = "";
    for (int i = 0; i < indent; i++) {
        indentStr += " ";
    }
    return indentStr;
}

Output:

{
  "firstName": "Json",
  "lastName": "Smith",
  "age": 30,
  "address":
  {
    "streetAddress": "666 1nd Street",
    "city": "New York",
    "state": "NY",
    "postalCode": 10021
  },
  "phoneNumbers":
  [
    {
      "type": "home",
      "number": "542 666-1234"
    },
    {
      "type": "fax",
      "number": "653 666-4567"
    }
  ],
  "friends":
  [
    {
      "firstName": "Test",
      "lastName": "Snow",
      "age": 20,
      "phoneNumbers":
      [
        {
          "type": "home",
          "number": "141 111-1234"
        }
      ],
      "friends":
      [
        {
          "firstName": "UnknownFirstName",
          "lastName": "UnknownLastName",
          "age": 999,
          "phoneNumbers":
          [
            {
              "type": "home",
              "number": "000 000-0000"
            }
          ]
        }
      ]
    },
    {
      "firstName": "Flash",
      "lastName": "Tompson",
      "age": 23,
      "phoneNumbers":
      [
        {
          "type": "home",
          "number": "999 111-1234"
        }
      ]
    }
  ]
}
 4
Author: , 2020-09-15 12:35:22

Here is general information about parsers, which can help you choose and understand what it can do. The text and table below are taken from the publication on Habrahabr: Java Programmer's Cheat Sheet 8. Libraries for working with Json, author of the article @Vedeninvyacheslav

There are the following methods of serialization and deserialization among the specified libraries (from the simplest to the most complex):

  1. Data bind
  2. Tree Model
  3. Streaming API
  4. XPath analogs (optional method)

Data bind

The most popular and easiest way is to simply specify the class, to be converted to json, can be part of the fields you mark annotations (and often even this is not necessary), and the library itself turns this class and its entire class hierarchy into json.

Pros: the simplest of the all of them

Cons: speed and memory. Most libraries use reflection, etc. methods for working with Java classes (although not all) that obviously not very fast. In addition, the entire json file at once turns into Java objects, which may just exhaust the entire available memory if you try to process a very large json.

Output: if there are no performance, memory problems and you are not going to processing multi-gigabyte json is probably the best way.


Tree Model

This parser represents json in the form of Java classes such as Node or `JsonElement with a hierarchical structure, and already itself the programmer bypasses them and gets information from them.

Pros: usually faster than the first method and easier than the third

Cons: inferior toData bind in simplicity, plus a number of libraries are able to generate classes with Data bind, rather than using reflection, in which case the Tree Model will not be faster. obviously, in addition, the problem of huge files and restrictions is not solved memory.


Streaming API

The lowest-level method, in fact, the programmer himself manually parses json tokens. But there are no restrictions on memory and in theory maximum performance.

Pros: performance and minimal memory consumption

Cons: difficulty using


XPath Analogs

Not very suitable if you need to get all information from json'a, but allows you to write an expression such as $.store.book[*].author to get a list of all authors of all books from the json 'a store. That is, it is easy to get part of information from json ' a.

Pros: allows you to quickly get information from json ' s by complex criteria

Cons: not very suitable when you need all the information from json 's, does not work in the opposite direction on the formation of json' s


Table of libraries and the parsing methods they support:

Способ\Hазвание  Fastjson  Gson  LoganSquare  JSONjava  Moshi  Jackson  Genson  JsonPath SimpleJson

Data bind          Да       Да       Да         -        Да       Да      Да       -         -
Tree Model         -        Да       -          Да       -        Да      -        -         Да
Streaming API      -        Да       -          -        -        Да      -        -         -
Аналоги XPath      Да       -        -          -        -        -       -        Да        -

Генерация классов  -        -        Да         -        -        -       -        -
 для Data bind*

Работает со        Да       Да       Нет        -        Да       Да      Да       -
static inner class**

Обязательность     Нет      Нет      Да         -        Нет      Нет     Нет      -
 аннотаций***

* - Generating classes for Data bind allows you to generate classes at the compilation stage, which in theory should give significant increase in library performance,

** - Works with static inner class makes sense only for the case of Data bind, is it possible to serialize and deserialize for the case of static inner classes (it is not recommended to serialize non-static inner classes),

*** - also only for the case of Data bind is it possible not to use annotations or is their use highly recommended,

 2
Author: Алексей Шиманский, 2017-12-26 13:09:44