Java serialize class to json

Сериализация в JSON

— Раз уж ты познакомился с JSON, давай поговорим о нем сегодня подробнее.

— Ок. А где обычно он используется?

— Обычно дело выглядит так. Кто-то (клиент) запрашивает у Java-программы (сервера) данные. Программа создает Java-объекты и заполняет их информацией из базы данных. Затем преобразовывает их в формат понятный запрашивающему (клиенту), например JSON, и отсылает их обратно.

Давай я тебе расскажу, как работать с ним из Java. Собственно, нам понадобятся только две вещи – сериализовать Java-объекты в JSON-формат и десериализовать Java-объекты из формата JSON.

Т.е. JSON – это стандарт транспортировки сообщений/данных от одной программы к другой. Таких стандартов довольно много. Но если программа написана на JavaScript, она обычно старается работать с JSON.

Сериализация в JSON - 1

Как ты уже знаешь, в Java есть встроенные стандартные средства сериализации. Но JSON к ним не относится. Поэтому если тебе надо использовать сериализацию объекта в JSON, ты можешь использовать один из популярных фреймворков(библиотек), которые это умеют.

— А чем отличаются различные фреймворки?

— Обычно они отличаются степенью сложности: есть фреймворки, которые умеют делать только самое необходимое, но они очень маленькие и простые. А есть и большие сложные фреймворки, которые могут делать гораздо больше.

Одним из популярных фреймворков считается Jackson. Мы рассмотрим работу с JSON на его примере.

Для начала тебе надо скачать этот фреймворк и добавить его себе в проект. Делать это надо в Intellij IDEA само собой. Загрузить фреймворк можно по ссылке.

Сконвертировать Java-объект в JSON примерно так же просто, как и сериализовать его. Для этого есть специальный класс ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper).

Давай я покажу тебе рабочий пример, а потом мы его разберем:

public static void main(String[] args) throws IOException < //создание объекта для сериализации в JSON Cat cat = new Cat(); cat.name = "Murka"; cat.age = 5; cat.weight = 4; //писать результат сериализации будем во Writer(StringWriter) StringWriter writer = new StringWriter(); //это объект Jackson, который выполняет сериализацию ObjectMapper mapper = new ObjectMapper(); // сама сериализация: 1-куда, 2-что mapper.writeValue(writer, cat); //преобразовываем все записанное во StringWriter в строку String result = writer.toString(); System.out.println(result); >

В строках 4-7 мы создаем объект класса Cat и заполняем его данными.

Строка 10 – создаем объект Writer, куда будем писать строку — JSON представление объекта.

Строка 13 – создаем объект ObjectMapper , который и выполняет всю сериализацию.

Строка 16 – пишем JSON-представление объекта cat в writer .

Строки 19-20 – выводим результат на экран.

Все выглядит довольно просто. Не сложнее родной сериализации в Java.

— А как будет выглядеть десериализация?

— Да почти так же, только короче:

public static void main(String[] args) throws IOException < String jsonString text-viola">"; StringReader reader = new StringReader(jsonString); ObjectMapper mapper = new ObjectMapper(); Cat cat = mapper.readValue(reader, Cat.class); >

Тут еще проще. Берем ObjectMapper и передаем в него строку с JSON или StringReader, а также класс объекта, который надо десериализовать . Вызываем метод readValue, и на выходе получаем готовый Java-объект со всеми данными.

— Ну, точно, как десериализация в Java.

— Почти. К объектам, которые сериализуются/десериализуются в JSON есть несколько требований:

1) поля должны быть видимые: или public или иметь getter’ы и setter’ы;

2) должен быть конструктор по умолчанию (без параметров).

— Ясно. Ожидаемо, в общем. Хотя Java отлично сериализовала и private поля.

— Так то — Java. У нее есть доступ к скрытым данным. От себя не утаишь.

Тут есть еще третий аспект. Надеюсь, ты обратил внимание на аннотацию @JsonAutoDetect в классе Cat?

— Ага. Как раз хотел спросить – что это такое.

— Это аннотации – служебная информация для фреймворка Jackson. Можно очень гибко управлять результатом сериализации в JSON формат, расставляя правильные аннотации.

— Круто! А что за аннотации есть?

Аннотация Описание
@JsonAutoDetect Ставится перед классом.
Помечает класс как готовый к сериализациив JSON.
@JsonIgnore Ставится перед свойством.
Свойство игнорируется при сериализации.
@JsonProperty Ставится перед свойством или getter’ом или setter’ом. Позволяет задать другое имя поля при сериализации.
@JsonPropertyOrder Ставится перед классом.
Позволяет задать порядок полей для сериализации.

— Есть много. Но не сейчас. Сейчас давай немного переделаем наш первый пример:

public static void main(String[] args) throws IOException < Cat cat = new Cat(); cat.name = "Murka"; cat.age = 5; cat.weight = 4; StringWriter writer = new StringWriter(); ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(writer, cat); String result = writer.toString(); System.out.println(result); >

Код остался тот же, но я поменяла аннотации: указала другое имя полю name — имя alias. А также отметила поле weight как Ignore, в результате JSON объекта поменялся.

— Хорошо, что можно так всего настраивать – думаю, мне это обязательно пригодится.

А десериализация поймет, как с этим работать? При десериализации из JSON в Java-объект, значение поля alias будет занесено в name объекта Cat?

— Да, десериализация будет работать как надо. Она умная.

Спасибо за такую интересную лекцию, Элли.

Источник

Работа с JSON на Java (библиотека GSON)

Заметка взята с сайта Javenue, так как несет много полезной информации. Спасибо ее автору.
Заметка была дополнена, поэтому если обнаружатся неточности — прошу писать мне. JSON, что означает JavaScript Object Notation, — это текстовый формат обмена данными, который легко читается человеком и в то же время является компактным (в отличии от того же XML формата). По сути это набор пар “ключ-значение”, объединенных в последовательность значений(массив). Допустим мы производим выборку информацию о заказчике из БД и возвращаем сведения о нем. Пример строки в формате JSON будет выглядеть так: Вообще, о самом формате JSON в Интернете написано более чем достаточно, ну а в этой статье я хочу рассмотреть бибилиотеку Gson для сериализации и десериализации java объектов в JSON.

1 Обзор библиотеки Gson

Gson — это небольшая java библиотека, которая позволяет конвертировать java объекты в их JSON представление, равно как и создавать объекты на основании их json представления. Изначально Gson был разработан в Google и использовался в нескольких внтуренних проектах. Через некоторое время было принято решение отдать библиотеку в open-source, чтобы она и дальше развивалась.

1.1 Подключение GSON

Сначала подключим библиотеку. Если вы используете в качестве сборщика Gradle, добавьте новую зависимость: compile ‘com.google.code.gson:gson:2.4’ Вот, что нужно прописать в файл pom.xml тем, кто использует Maven:

 com.google.code.gson gson 2.8.0 

1.2 Использование GSON

Основным классом библиотеки есть одноименный класс Gson. Для того, чтобы создать экземпляр класса нужно воспользоваться одним из двух способов:

Gson gson = new Gson(); Gson gson = new GsonBuilder().create();

Первый способ создаст инстанс класса с настройками по умолчанию, а второй способ позволит применить некоторые настройки. О настройках расскажу чуть ниже. Основные методы, которые используются для сериализации и десериализации java-объектов, называются toJson и fromJson .

2 Сериализация и десериализация в Gson

Gson gson = new Gson(); gson.toJson(123); // 123 gson.toJson("hello"); // "hello" gson.toJson(Long.valueOf(10)); // 10
Integer integer = gson.fromJson("1", int.class); String string = gson.fromJson("\"world\"", String.class); Boolean bool = gson.fromJson("true", Boolean.class);

Так как инстанс Gson не имеет внутреннего состояния, то его можно переиспользовать произвольное количество раз, а так же использовать в многопоточных приложениях. Идем дальше. Вот таким образом можно сериализовать и десеарелизовать массив:

String string = gson.toJson(new int[] < 10, 100 >); // [10,100] int[] array = gson.fromJson("[10,100]", int[].class)

С объектами, которые в качестве полей содержат строки и примитивы, все тоже достаточно просто. Допустим, у нас в приложении описан следующий класс:

public static class Entity < volatile int id; String name; transient long random; public Entity(int id, String name) < this.id = id; this.name = name; >>
Entity entity = new Entity(100, "name"); entity.random = 1234;
String json = gson.toJson(entity); // Entity read = gson.fromJson(json, Entity.class); System.out.println(read.random); // 0

Обратите внимание, что при сериализации значение поля random не было сохранено. Все дело в том, что поведение библиотеки по-умолчанию не сериализует поля, помеченные модификатором transient . О том, как изменить это поведение, читайте в разделе про GsonBuilder .

3 Работа с коллекциями

  • метод toJson для Collection вернет массив объектов или примитивов;
  • метод toJson для Map вернет ассоциативный массив.

С десериализацией все немного сложнее. Рассмотрим следующий пример:

Map map = new LinkedHashMap<>(); map.put("USD", 123); map.put("EUR", 321); String json = gson.toJson(map); Type type = new TypeToken()<>.getType(); Map read = gson.fromJson(json, type);

Обратите внимание как мы определили тип для коллекции при десериализации. К сожалению, сделать это как-то проще не получится.

Допустим, вам необходимо конвертировать коллекцию, содержащую объекты различных типов. В этом случае с сериализацией проблем не возникнет, например:

Collection collection = new ArrayList(); collection.add("string"); collection.add(10); collection.add(new Entity(11, "text")); gson.toJson(collection); // ["string",10,]

А вот десереализовать такую коллекцию не получится, так как Gson не сможет найти правильные соответствия для типов данных.

Одним из самых хороших решений этой проблемы будет использование низкоуровневого API — классы JsonElement, JsonPrimitive, JsonObject и так далее. Некоторое представление о том, как это сделать, вы сможете получить в следующем разделе статьи.

4 Определяем свои правила конвертации объектов

Gson позволяет разработчикам определять свои собственные правила для сериализации и десериализации объектов. Зарегистрировать их можно с помощью метода registerTypeAdapter() .

Допустим, у нас в приложении есть следующий класс:

public static class Custom < Date date; BigInteger integer; public Custom(Date date, BigInteger integer) < this.date = date; this.integer = integer; >>

Для кастомного сериализатора необходимо реализовать интерфейс JsonSerializer , а для десериализаторв — соответственно JsonDeserializer . Для простоты можно создать один класс, который реализует оба эти интерфейса:

public class CustomConverter implements JsonSerializer, JsonDeserializer  < public JsonElement serialize(Custom src, Type type, JsonSerializationContext context) < JsonObject object = new JsonObject(); object.addProperty("date", src.date.getTime()); object.addProperty("integer", src.integer.toString()); return object; >public Custom deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException < JsonObject object = json.getAsJsonObject(); Date date = new Date(object.get("date").getAsLong()); BigInteger integer = new BigInteger(object.get("integer").getAsString()); return new Custom(date, integer); >>

Зарегистрировать наш класс можно следующим образом:

GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(Custom.class, new CustomConverter()); Gson gson = builder.create();

5 Настройки Gson и класс GsonBuilder

По умолчанию результат сериализации в json будет компактным, то есть все лишние whitespace символы будут удалены. Это позволит, например, уменьшить траффик при передачи JSON объектов по сети.

Метод setPrettyPrinting у класса GsonBuilder меняет это поведение и сериализует объекты в удобную для человека форму с пробелами и переводами строк. Пример вы можете посмотреть по ссылке приведенной в начале статьи.

Еще одна полезная настройка для GsonBuilder — excludeFieldsWithModifiers . Она позволяет изменить набор несериализуемых полей при конвертации java объектов в JSON. По умолчанию игнорируются только поля с модификатором transient .

6 Пример использования GSON

Нам надо преобразовать данные JSON в Java-объект. Пусть у нас имеется класс Student , представляющий заказчика, с определенными полями: имя и курс.

public class Student < @SerializedName("name") private String name; @SerialazedName("course") private int course; public Student() < >public Student(String name, int course) < this.name = name; this.course = age; >public String getName() < return name; >public void setName(String name) < this.name = name; >public int getCourse() < return course; >public void setCourse(int course) < this.course = course; >>

Аннотация @SerializedName используется для изменения выходного имени свойства при сериализации, если это потребуется.

Итак, мы получили объект в виде строки, например такой объект может прийти приложению-клюиенту от сервера или может быть считан с файла. Для выполнения парсинга нам необходимо получить объект класса Gson , для этого удобно использовать GsonBuilder . Преобразование JSON в объект класса Student выполняется методом Gson.from() :

import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class Example < public static void main(String[] args) < String str = ""; GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create(); Student student = gson.fromJson(str, Student.class); System.out.println("Имя: " + student.getName() + "\nКурс: " + student.getCourse()); > >

Например, можно считывать объекты из файла по одному. Однако, если у вас есть корректный JSON файл или сервер прислал сразу массив объектов — то их можно сразу преобразовать в массив. Например, при запросе истории погоды или курса валют за период сервер мог бы прислать вам массив однотипных объектов.

Type collectionType = new TypeToken>()<>.getType(); Collection = gson.fromJson(response, collectionType);

Здесь методу fromJson() мы в качестве второго параметра должны передаем тип нашей коллекции.

Источник

Читайте также:  Разделить элементы массива php
Оцените статью