Reading and Writing JSON Files in Java
JSON (JavaScript Object Notation) is a light-weight, human-readable, and language-independent data exchange format. Originally derived from JavaScript in the early 2000s, JSON has quickly become a de-facto standard format for exchanging data between the servers and the clients.
JSON has only two data structures: objects and arrays. An object is an unordered set of zero or more key-value pairs. An array is a list of zero or more values. The values can be strings, numbers, booleans, null, nested objects, and arrays.
Almost all programming languages including Java, Python, Node.js, JavaScript, and Ruby provide code to generate and parse the JSON data. In this article, you'll learn how to read and write JSON in Java.
Let us create a simple JSON file which contains a single object that describes a customer, as shown below:
Unfortunately, Java does not provide any native library for processing JSON. In this article, we will look at some of the best open-source libraries available for generating and parsing JSON in Java.
JSON.simple is a simple library for processing JSON data in Java. It allows you to read, write, parse, and query JSON in full compliance with JSON specifications (RFC4627).
To add JSON.simple to your Gradle project, add the following dependency to build.gradle file:
For Maven, include the below dependency to your pom.xml file:
Here is an example that demonstrates how to use JSON.simple library to write JSON data to a file:
As you can see above, we are using the JsonObject and JsonArray classes to generating a customer object with personal details, projects, payment methods, and more. The JsonObject class is used to create a JSON object with unordered key-value pairs. The JsonArray class is used to create a JSON array with multiple objects.
Let us now read JSON from the file we just created above. JSON.simple provides the Jsoner.deserialize() static method for parsing a JSON file. Here is an example:
In the above example, we are creating a JsonObject object by explicitly casting the object returned by the Jsoner.deserialize() method. We then read the JSON objects one-by-one by casting them to their actual data type.
Jackson is another popular Java library for reading and writing JSON data. Jackson provides the ObjectMapper class to convert Java Objects into their JSON representation. It can also be used to convert a JSON object back to an equivalent Java object.
Just add the following dependency to your Gradle project's build.gradle file to include the Jackson support:
For Maven, add the below dependency to your pom.xml file:
Note: If you are looking to parse JSON data in Spring Boot, check out the Processing JSON Data in Spring Boot guide.
ObjectMapper provides the writeValue() method to convert a Java object to a JSON string. The following example shows how to use the Jackson library to write JSON data to a file:
As you can see above, we are using the writeValueAsString() method to serialize a map object to a JSON string. The generated JSON string is then written to the file.
Reading JSON from a file using Jackson is easier than the JSON.simple library. The ObjectMapper class can also be used to construct a hierarchical tree of nodes from JSON data. In the JSON tree model, you can access a specific node and read its value. In the tree model, each node is of type JsonNode which provides different methods to work with specific keys.
Here is an example that parses the customer.json file by using the Jackson library:
Gson is yet another Java library, developed and maintained by Google, for converting Java Objects into their JSON representation. You can also use it to convert a JSON string back to an equivalent Java object.
Gson provides simple toJson() and fromJson() methods that you can use to easily convert a Java object to and from JSON.
To add Gson to your Gradle project, add the below dependency to the build.gralde file:
For Maven, add the following dependency to your pom.xml file:
The following example demonstrates how to use the toJson() method to convert a Java collection to a JSON string and then write it to a file:
The above code looks very much similar to Jackson's code for writing JSON to a file. The only difference is we are now using the toJson() method from the Gson class for converting the collection to a JSON string.
We can use the JsonParser class that comes with the Gson library to parse the JSON file we just created. Here is an example:
Moshi is another powerful JSON library created by Square for Kotlin and Java. It makes it easy to parse JSON into Java objects as well as convert Java Objects into their JSON representation. Moshi has built-in support for reading and writing Java's core data types including primitives, collections, strings, and enums.
If you want to use Moshi in a Gradle project, include the following dependency to your build.gradle file:
For Maven, add the below dependency to your pom.xml file:
Moshi provides the JsonWriter class that can be used to write a JSON encoded value to a stream, one token at a time, as shown below:
As you can see above, we have created an instance of JsonWriter to encode our data as JSON. We then called different methods on the write object to create a JSON object with nested objects and arrays.
Let us use the JsonReader class provided by Moshi to parse JSON from a file. It reads a JSON encode value as a stream of tokens. This stream includes both literal values (strings, numbers, booleans, and nulls) as well as the begin and end delimiters of objects and arrays. The tokens are traversed in depth-first order, the same order that they appear in the JSON document. Within JSON objects, name-value pairs are represented by a single token.
Here is an example:
That's all folks for reading and writing JSON files in Java. There are no native libraries for efficiently processing JSON data in Java.
In this article, I have discussed four different open-source libraries for reading, writing, and parsing JSON data in Java. These libraries include JSON.simple, Jackson, Gson, and Moshi.
So what's the best JSON library? Personally, I use and recommend Jackson. It is a suite of data processing tools for Java that can be used to parse not only JSON but other data formats too like CSV, XML, YAML, and more.
If you are looking to read and write XML, check out Reading and Writing XML in Java tutorial.
✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.
How to Parse JSON in Java
In this tutorial we will look at how to parse JSON in Java using different libraries.
JSON stands for JavaScript Object Notation, and it is based on a subset of JavaScript.
As a data-exchange format, it is widely used in web programming. Here we show how to parse JSON in Java using the org.json library.
A JSON object is an unordered set of key/value pairs. A JSON array is an ordered collection of values. The values themselves could be objects or arrays.
We will be parsing this JSON as an example to retrieve values for pageName , pagePic and post_id
Parse JSON Using org.json
To use org.json to parse JSON in Java, you need to add the library as a dependency. This can be fetched from Maven repository
N.B. the . needs to be replaced by the JSON string. This has been omitted from the code above for clarity.
First, we need to convert the JSON string into a JSON Object, using JSONObject class.
Also, note that “pageInfo” is a JSON Object, so we use the getJSONObject method.
Likewise, “posts” is a JSON Array, so we need to use the getJSONArray method.
Parse JSON Using Gson
In order to use Gson to parse JSON in Java, you need to add the library as a dependency. You can get the latest version from Maven repository
The below example shows how to Parse the above JSON with Gson.
Like the previous example, the . needs to be replaced by the JSON string.
Parse JSON Using JsonPATH
The above two examples require a full deserialization of the JSON into a Java object before accessing the value in the property of interest. Another alternative, which does not go this route is to use JsonPATH which is like XPath for JSON and allows traversing of JSON objects.
Like before, you need to add JsonPATH as a dependency, which can be fetched from Maven repository
Чтение и запись JSON на Java
Обозначение объектов JavaScript или, короче говоря, JSON -это формат обмена данными, который был введен в 1999 году и получил широкое распространение в середине 2000-х годов. В настоящее время это де-факто стандартный формат для общения между веб-сервисами и их клиентами (браузерами, мобильными приложениями и т.д.). Знание того, как читать и писать, является необходимым навыком для любого разработчика программного обеспечения.
Несмотря на то, что ДЖЕЙСОН был получен из JavaScript, это независимый от платформы формат. Вы можете работать с ним на нескольких языках программирования, включая Java, Python, Ruby и многие другие. Действительно, любой язык, который может анализировать строку, может обрабатывать JSON.
Популярность JSON привела к его встроенной поддержке многими базами данных, последние версии PostgreSQL и MySQL содержат встроенную поддержку запроса данных, хранящихся в полях JSON. Базы данных NoSQL, такие как MongoDB , были построены на основе этого формата и используют документы JSON для хранения записей, точно так же, как таблицы и строки хранят записи в реляционной базе данных.
Одним из основных преимуществ JSON по сравнению с форматом данных XML является размер документа. Поскольку JSON не имеет схем, нет необходимости переносить огромные структурные накладные расходы, такие как пространства имен и оболочки.
JSON-это универсальный формат данных, который имеет шесть типов данных:
- Строки
- Числа
- Логический
- Массивы
- Объекты
- нулевой
Давайте взглянем на простой документ JSON:
Эта структура определяет объект, представляющий человека по имени “Бенджамин Уотсон”. Здесь мы можем ознакомиться с его подробностями, такими как его возраст, семейное положение и хобби.
По сути, объект JSON – это не более чем строка. Строка, представляющая объект, поэтому объекты JSON часто называются Строками JSON или документами JSON .
json-просто
Поскольку в Java нет встроенной поддержки JSON, прежде всего, мы должны добавить новую зависимость, которая обеспечивала бы ее для нас. Для начала мы будем использовать модуль json-simple , добавив его в качестве зависимости Maven.
Этот модуль полностью соответствует спецификации JSON RFC4627 и обеспечивает основные функциональные возможности, такие как кодирование и декодирование объектов JSON, и не имеет никаких зависимостей от внешних модулей.
Давайте создадим простой метод, который будет принимать имя файла в качестве параметра и записывать некоторые жестко закодированные данные JSON:
Здесь мы создаем экземпляр класса JSONObject , указывая имя и возраст в качестве свойств. Затем мы создаем экземпляр класса JSONArray , добавляя два строковых элемента и помещая его в качестве третьего свойства нашего sampleObject . В конечном счете, мы преобразуем образец объекта в документ JSON, вызывающий метод toJSONString() и записываем его в файл.
Чтобы запустить этот код, мы должны создать точку входа в наше приложение, которая могла бы выглядеть следующим образом:
В результате выполнения этого кода мы получим файл с именем example.json в корне нашего пакета. Содержимое файла будет документом JSON со всеми свойствами, которые мы ввели:
Отлично! У нас только что был наш первый опыт работы с форматом JSON, и мы успешно сериализовали в него объект Java и записали его в файл.
Теперь, с небольшим изменением нашего исходного кода, мы можем прочитать объект JSON из файла и распечатать его на консоли либо полностью, либо распечатать выбранные отдельные свойства:
Важно отметить, что метод parse() возвращает Объект , и мы должны явно привести его к JSONObject .
Если у вас неправильный или поврежденный документ JSON, вы получите исключение, подобное этому:
Чтобы смоделировать это, попробуйте удалить последнюю закрывающую скобку > .
Копать Глубже
Несмотря на то, что json-простой полезен, он не позволяет нам использовать пользовательские классы без написания дополнительного кода. Давайте предположим, что у нас есть класс, представляющий человека из нашего первоначального примера:
Нашей задачей было бы десериализовать этот объект из файла в экземпляр класса Person . Давайте сначала попробуем сделать это с помощью simple-json .
Изменив наш метод main () , повторно используя статический readSimpleJsonDemo() и добавив необходимый импорт, мы доберемся до:
Это выглядит не очень хорошо, у нас много странных типов, но, похоже, это делает свою работу, верно?
Git Essentials
Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!
Ну, не совсем так…
Давайте попробуем распечатать на консоли массив дети нашего Человека , а затем возраст первого ребенка.
Как мы видим, первый вывод консоли показывает, казалось бы, хороший результат:
но второй выдает Исключение :
Проблема здесь в том, что наш тип в Список<Человек> не создал два новых Человека объекта, он просто вставил все, что там было – JSONObject в нашем текущем случае. Когда мы попытались копнуть глубже и узнать фактический возраст первого ребенка, мы столкнулись с ClassCastException .
Это большая проблема, которую, я уверен, вы сможете преодолеть, написав кучу очень умного кода, которым вы могли бы гордиться, но есть простой способ сделать это с самого начала.
Джексон
Библиотека, которая позволит нам делать все это очень эффективно, называется Джексон . Это очень распространено и используется в крупных корпоративных проектах, таких как Спящий режим .
Давайте добавим его в качестве новой зависимости Maven:
Основной класс , который мы будем использовать, называется ObjectMapper , у него есть метод readValue () , который принимает два аргумента: источник для чтения и класс для приведения результата.
ObjectMapper может быть настроен с несколькими различными параметрами, переданными в конструктор:
| FAIL_ON_SELF_РЕФЕРЕНЦИИ | Функция, которая определяет, что происходит, когда прямая самоссылка обнаруживается POJO (и для нее не включена обработка идентификатора объекта): либо создается исключение JsonMappingException (если это правда), либо ссылка обычно обрабатывается (ложь). |
| ОТСТУП_ВЫХОД | Функция, которая позволяет включать (или отключать) отступы для базового генератора, используя принтер pretty по умолчанию, настроенный для ObjectMapper (и авторов объектов, созданных из mapper). |
| ORDER_MAP_ENTRIES_BY_KEYES | Функция, определяющая, будут ли записи карты сначала отсортированы по ключу перед сериализацией или нет: если включено, при необходимости выполняется дополнительный шаг сортировки (не требуется для отсортированных карт), если отключено, дополнительная сортировка не требуется. |
| USE_EQUALITY_FOR_OBJECT_ID | Функция, определяющая, сравнивается ли идентичность объекта с использованием истинной идентичности объекта на уровне JVM (ложь); или метод equals (). |
| Функция, определяющая, как сериализуется тип char []: при включении сериализуется как явный массив JSON (с односимвольными строками в качестве значений); при отключении по умолчанию сериализуется как строки (что более компактно). | |
| МЕТКИ ВРЕМЕНИ WRITE_DATE_KEYS_AS_TIMESTAMPS | Функция, определяющая, будут ли даты (и подтипы), используемые в качестве ключей карты, сериализованы как метки времени или нет (если нет, будут сериализованы как текстовые значения). |
| WRITE_DATE_TIMESTAMPS_АС_НАНОСЕКУНДЫ | Функция, которая определяет, следует ли записывать числовые значения временных меток с использованием наносекундных временных меток (включено) или нет (отключено); если и только если тип данных поддерживает такое разрешение. |
| МЕТКИ ВРЕМЕНИ WRITE_DATES_AS_TIMESTAMPS | Функция, которая определяет, следует ли сериализовать значения даты (и даты/времени) (и такие вещи, основанные на данных, как календари), как числовые метки времени (true; по умолчанию) или как что-то другое (обычно текстовое представление). |
| WRITE_DATES_С_ЗОНОМ_ИД | Функция, которая определяет, следует ли сериализовать значения даты/времени так, чтобы они включали идентификатор часового пояса, в тех случаях, когда сам тип содержит информацию о часовом поясе. |
Полный список сериализации перечисления доступен здесь .
К сожалению, после запуска этого фрагмента кода мы получим исключение:
Судя по всему, мы должны добавить конструктор по умолчанию в класс Person :
При повторном запуске кода мы увидим еще одно исключение:
Этот вопрос немного сложнее решить, так как сообщение об ошибке не говорит нам, что делать для достижения желаемого результата. Игнорирование свойства не является жизнеспособным вариантом, поскольку мы явно указываем его в документе JSON и хотим, чтобы он был переведен в результирующий объект Java.
Проблема здесь связана с внутренней структурой библиотеки Джексона. Он выводит имена свойств из геттеров, удаляя их первые части. В случае getafe() и getName() это работает отлично, но с женат() это не так, и предполагается, что поле должно называться женат вместо Женат .
Грубый, но рабочий вариант – мы можем решить эту проблему, просто переименовав получателя в is Женат . Давайте продолжим и попробуем это сделать.
Больше никаких исключений не появляется, и мы видим желаемый результат!
Хотя результат удовлетворяет, есть лучший способ обойти это, чем добавлять еще один is к каждому из ваших логических геттеров.
Мы можем достичь того же результата, добавив аннотацию к методу женат() :
Таким образом, мы явно сообщаем Джексону название поля, и ему не нужно угадывать. Это может быть особенно полезно в тех случаях, когда поле называется совершенно иначе, чем геттеры.
Вывод
JSON-это легкий текстовый формат, который позволяет нам представлять объекты и передавать их через Интернет или хранить в базе данных.
В Java отсутствует встроенная поддержка манипуляций с JSON, однако существует несколько модулей, обеспечивающих эту функциональность. В этом уроке мы рассмотрели модули json-simple и Jackson , показав сильные и слабые стороны каждого из них.
Работая с JSON, вы должны иметь в виду нюансы модулей, с которыми вы работаете, и тщательно отлаживать исключения, которые могут появляться.