Often there is a need to work with Json , in particular, its reading and parsing. In Java , you usually know what type of variables you work with, and when parsing , Json is confused that there can be any type of fields.

What are the ways to parse Json ? How to do it?

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

    4 answers 4

    Data can be obtained in different ways and, of course, 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 that nothing is copied into the answer.


    Simple json

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

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

    • JSONArray can include several JSONObject , you can loop around it at each iteration to get a JSONObject .
    • JSONObject is an object from which its individual properties can be retrieved.

    I would use it for small Json lines, where you don’t need to bother much, or if you’re too lazy to write your handler class based on the code shown 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 to List, Map, etc.


    GSON

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

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

    Allows parsing Json as well as Json-simple , i.e. using JSONObject and JSONArray (see the documentation ), but has a more powerful parsing tool. It is enough to create classes that repeat the structure of Json 'a. To parse the 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 suffices to write:

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

    Everything! Magic! Miracle! Now in the person is an object with the type Person , in which there is data with exactly those types that were specified in the created classes! Now you can work with any type, as you always used to 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 the 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; } 

    ...... 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 during parsing, change the variable name (for example, not personFirstName , but fName ) and much more. See the documentation for details.


    Jackson

    Where to get: 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 can also parse based on the provided classes (see example below).

    Similarly, it can be used to specify additional requirements due to annotations, for example: not parsit the specified fields, use the custom class constructor, change the variable name (for example, not firstName , but fName ) and much more. See the documentation for details.

     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 / repository on github

    Refers to the so-called XPath libraries. Its essence is similar to xpath in xml , that is, it is easy to get some of the information from json 'a, along the specified path. And 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 

    An example with a sample by the 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 
    • 3
      GSON also has the ability to change behavior with annotations - rjhdby
    • I understand why the vehicle asked such a question and answered it himself, for they really got the questions of newbies how to parse Json . I propose to make the answer general and to questions on Json further put doubles with reference to this answer. - Barmaley
    • @Barmaley I would suggest writing more answers, so that at least the answer would not be gigantic. And I also want to ask YuriySPb to separately write answers on Android, I think there is something separate there too - Alexey Shimansky
    • @rjhdby added this nuance to the answer. - Alexey Shimansky
    • @Barmaley, you don’t need to do anything common - Qwertiy

    Some more options


    Logan square

    LoganSquare - based on Jackson 's streaming API. According to the demonstrated tests , GSON and Jackson are faster. Therefore good for Android.

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

    Usage: 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!"); } } 

    analysis:

     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.

    Good, according to the developers, to work with Android.

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

    • An example of parsing Json strings into a Person object:

       Moshi moshi = new Moshi.Builder().build(); JsonAdapter<Person> jsonAdapter = moshi.adapter(Person.class); Person person = jsonAdapter.fromJson(jsonStringPerson); // В person будут все данные 
    • Example of parsing in the 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: here / repository on github / or via Maven , etc.

    Documentation: http://owlike.imtqy.com/genson/Documentation/UserGuide/

    By creating a POJO (creating classes that repeat the structure of Json 'a), the object is parsed from the string, stuffed along the required fields of the objects. It is possible to filter properties, include or exclude fields when parsing, rename, the 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 the list:

       List<Object> persons = genson.deserialize("[{\"age\":28,\"name\":\"Foo\"}, {\"age\":30,\"name\":\"Bar\"}]", List.class); // persons - список с данными объектов 
    • Example of parsing in the 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: via Maven and other collectors / repository on github . Directly the description of work with xpath . Caution, ̶n̶e̶n̶o̶r̶m̶a̶t̶i̶v̶n̶a̶ya̶ ̶l̶e̶k̶s̶i̶k̶a̶ Chinese.

    Refers to xpath counterparts.

    The usual way:

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

    XPpath application

     // Выведет все фамилии друзей 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 } 

      JSON-P

      Supports JSON serialization and parsing without 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> 

      JSON string parsing example:

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

      An example of outputting 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; } 

      Conclusion:

       { "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" } ] } ] } 
      • Поддерживает сериализацию и парсинг JSON без предварительного маппинга в классах - because it’s a manual parse where the developer knows the structure and needs to write bicycles in the same way as the Simple Json%) - Alexey Shimansky
      • разработчику известна структура - not known, the structure can be any. - Drakonoved
      • When the structure is known, you can probably see another sjr specification number 367 or json-b (json binding) - Sergey

      Here is the general information about parsers, which can help in the selection and understand what he can do. The text and table presented below are taken from the publication on Habrahabr : Java programmer cheat sheet 8. Libraries for working with Json , author of the article @ VedeninVyacheslav

      There are the following ways 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)

      Data bind

      The most popular and simplest way is you simply specify the class that needs to be converted to json , maybe some of the fields are annotated (and often even not necessary), and the library itself turns this class and its entire class hierarchy into json .

      Pros : the most simple of all

      Cons : speed and memory. Most libraries use reflection, etc. methods for working with Java classes (although not all), which is obviously not very fast. In addition, the entire json file is immediately converted to Java objects, which can simply exhaust all available memory if you try to process very large json .

      Conclusion : if there are no problems with performance, memory and you are not going to handle multi- gigabyte json'y, most likely 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 the programmer himself bypasses them and obtains information from them.

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

      Minuses : Data bind is inferior in simplicity, plus a number of libraries are able to generate classes with Data bind , and not use reflection, in this case, the fact that the Tree Model will not be faster is obvious, and the problem of huge files and memory limitations are not solved.


      Streaming api

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

      Pros : performance and minimum memory consumption

      Cons : difficulty of use


      Xpath analogs

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

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

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


      Library table and 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** Обязательность Нет Нет Да - Нет Нет Нет - аннотаций*** 

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

      ** - Works with the static inner class only makes sense for the case of Data bind, is serialization and deserialization possible for the case of static inner classes (non-static inner classes are not recommended to be serialized),

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