Конвертация объекта в json java

JSON serialization frameworks

— Я тут смотрю, тебя познакомили с азами сериализации в JSON?

— Почему с азами? Я уже много знаю!

— Святая простота. Да ты и половины не знаешь. Процентов 10 от силы.

— Ух ты. А что там еще осталось?

— Десериализация иерархии объектов (полиморфизм при десериализации), десериализация коллекций, еще много всего. Jackson – большой и мощный фреймворк, а ты с ним, откровенно говоря, едва познакомился.

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

Приятно становиться умнее с каждой лекцией!

— Как не помочь другу-роботу? Кто если не я?

Как ты уже убедился, аннотации используются не только при сериализации, но и при десериализации. На практике для сериализации надо гораздо меньше информации, чем для десериализации. Пример:

class Cat < public String name = "murka"; public Cat[] cats = new Cat[0]; >
class Cat < public String name = "murka"; public List cats = new ArrayList<>(); >
class Cat < public String name = "murka"; public List cats = new LinkedList<>(); >

Объекты типов Array(массив), ArrayList, LinkedList,… заменяются на массив в JSON-формате.

А вот при десериализации неясно, какой объект создать — ArrayList или LinkedList?

— Согласен, если у класса есть поле, и тип поля – это интерфейс (как в случае с public List cats ), то совсем не ясно, какой именно объект ему присваивать.

— Можно добавить этому полю дополнительные аннотации или оставить jackson-у настройки по умолчанию. Смотри пример:

 public class Solution < public static void main(String[] args) throws IOException < String jsonString = "<\"name\":\"Murka\",\"cats\":[<\"name\":\"Timka\">,]>"; ObjectMapper mapper = new ObjectMapper(); Cat cat = mapper.readValue(jsonString, Cat.class); System.out.println(cat); System.out.println(cat.cats.getClass()); > > 

Т.е. мы не вмешиваемся и jackson сам определяет классы, которые будут использоваться при десериализации.

— А мне нравится. Удобно. Если конкретная реализация не имеет значения, можно не утруждать себя дополнительными настройками.

Ты еще говорил, что можно воспользоваться аннотациями. Это как?

— Да ничего сложного. Пример:

 public class Solution < public static void main(String[] args) throws IOException < String jsonString = "<\"name\":\"Murka\",\"cats\":[<\"name\":\"Timka\">,]>"; ObjectMapper mapper = new ObjectMapper(); Cat cat = mapper.readValue(jsonString, Cat.class); System.out.println(cat); System.out.println(cat.cats.getClass()); > > 

В строке 3 мы просто добавили аннотацию @JsonDeserialize(as = LinkedList.class) , где указали, какую реализацию интерфейса List использовать.

— Ага. Ясно. Действительно – довольно просто.

— Но и это еще не все. Теперь представь, что тип данных в List тоже интерфейс! Что ты будешь делать?

— У нас есть аннотация и на этот случай?

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

Тип коллекции Как задать тип данных
List @JsonDeserialize(contentAs=ValueTypeImpl.class)
Map @JsonDeserialize(keyAs=KeyTypeImpl.class)

— Круто. Действительно, много нужных аннотаций для разных случаев, о которых заранее и не догадаешься.

— И это еще не все. Сейчас будет самое вкусное. В реальных проектах, классы данных очень часто унаследованы от одного базового класса или интерфейса, который используется практически везде. И вот представь, тебе надо десериализовать структуру данных, которая содержит такие классы. Пример:

public static void main(String[] args) throws IOException < Cat cat = new Cat(); cat.name = "Murka"; cat.age = 5; Dog dog = new Dog(); dog.name = "Killer"; dog.age = 8; dog.owner = "Bill Jeferson"; ArrayListPet> pets = new ArrayListPet>(); pets.add(cat); pets.add(dog); StringWriter writer = new StringWriter(); ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(writer, pets); System.out.println(writer.toString()); >
@JsonAutoDetect class Pet < public String name; > @JsonAutoDetect class Cat extends Pet < public int age; > @JsonAutoDetect class Dog extends Pet < public int age; public String owner; >

Обрати внимание на результат сериализации.

Мы не сможем провести десериализацию этих данных обратно в Java-объекты, т.к. они фактически неразличимы.

— Немного различимы — у Dog есть поле owner.

— Да, но это поле может быть равно null или вообще пропускаться при сериализации.

— А разве мы не можем задать тип данных с помощью известных нам аннотаций?

— Нет. В одной коллекции после десериализации должны хранится различные объекты типа Cat, Dog и еще пары десятков классов, которые можно унаследовать от Pet.

— И что же можно тут сделать?

Во-первых, выделяют некоторое поле, которое используется для того, чтобы отличать один тип от другого. Если его нет – его заводят.

Во-вторых, есть специальные аннотации, которые позволяют управлять процессом «полиморфной десериализации». Вот что можно сделать:

public static void main(String[] args) throws IOException < Cat cat = new Cat(); cat.name = "Murka"; cat.age = 5; Dog dog = new Dog(); dog.name = "Killer"; dog.age = 8; dog.owner = "Bill Jeferson"; House house = new House(); house.pets.add(dog); house.pets.add(cat); StringWriter writer = new StringWriter(); ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(writer, house); System.out.println(writer.toString()); >
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property="type") @JsonSubTypes(< @JsonSubTypes.Type(value=Cat.class, name text-user">cat"), @JsonSubTypes.Type(value=Dog.class, name text-user">dog") >) class Pet < public String name; > class Cat extends Pet < public int age; > class Dog extends Pet < public int age; public String owner; > class House < public List<Pet> pets = new ArrayList<>(); >

С помощью аннотаций мы указываем, что JSON-представление будет содержать специальное поле type , которое будет хранить значение cat , для класса Cat и значение dog , для класса Dog . Этой информации достаточно, чтобы выполнить корректную десериализацию объекта: при десериализации по значению поля type будет определяться тип объекта, который надо создать.

Иногда в качестве значения поля type используют имя класса (например, «com.example.entity.Cat.class»), но это не очень хорошо. Зачем стороннему приложению, которому мы пересылаем JSON, знать, как называются наши классы? К тому же, классы иногда переименовывают. Использование некоего уникального имени для обозначения конкретного класса – предпочтительнее.

— Круто! А я и не знал, что десериализация такая сложная вещь. И что столько всего можно настраивать.

— Ага. Это действительно новые для тебя вещи, но именно благодаря таким практическим знаниям, ты скоро станешь крутым программистом.

— Амиго – крутой программист. Круто!

Источник

Конвертация Java объектов в JSON

Конвертация Java объектов есть одним из часто-используемых в разработке WEB-ресурсов. В этом уроке я покажу, как конвертировать Java объект в JSON или с JSON в Java объект.

Шаг 1

Для того чтобы манипулировать конвертированием мы будем использовать библиотеку Jackson.

Давайте создадим Maven project и добавим в pom.xml следующие зависимости:

  com.fasterxml.jackson.core jackson-core 2.2.2  com.fasterxml.jackson.core jackson-databind 2.2.2  com.fasterxml.jackson.core jackson-annotations 2.2.2  

Шаг 2

Теперь добавим POJO который мы и будем конвертировать:

package pojo; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; public class User < @JsonProperty("Number") private long id; @JsonProperty("First Name") private String name; @JsonProperty("Phone Number") private String phone; @JsonIgnore private String level; public User() < >public User(long id, String name, String phone, String level) < this.id = id; this.name = name; this.phone = phone; this.level = level; >public long getId() < return id; >public void setId(long id) < this.id = id; >public String getName() < return name; >public void setName(String name) < this.name = name; >public String getPhone() < return phone; >public void setPhone(String phone) < this.phone = phone; >public String getLevel() < return level; >public void setLevel(String level) < this.level = level; >@Override public String toString() < return "User[ID:" + id + ", Name: " + name + ", Phone: " + phone + "]"; >>

Обратите внимание, обязательно должен быть пустой конструктор и getter & setter.

Как вы видите мы используем две аннотации:

@JsonProperty(“name”) – эта говорит, что данный атрибут в JSON будет именоваться как name

@JsonIgnore – а эта аннотация игнорирует данный атрибут и в результате конвертирования он не будет добавлен в JSON.

Шаг 3

Теперь создадим класс конверте где будут все методы, и назовем его Converter.java:

package util; import com.fasterxml.jackson.databind.ObjectMapper; import pojo.User; import java.io.File; import java.io.IOException; public class Converter < private final static String baseFile = "user.json"; public static void toJSON(User user) throws IOException < ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(new File(baseFile), user); System.out.println("json created!"); >public static User toJavaObject() throws IOException < ObjectMapper mapper = new ObjectMapper(); return mapper.readValue(new File(baseFile), User.class); >>

В результате выполнения появится файл user.json:

И после конвертации обратно в POJO мы получим объект с полями:

User[ID:1, Name: Alex, Phone: +38000000001]

Возникнут вопросы, выслушаю вас в комментариях.

ПОХОЖИЕ ПУБЛИКАЦИИ

16 комментариев к статье «Конвертация Java объектов в JSON»

Спасибо за статью, как раз сейчас разбираюсь с JSON. Может есть у вас в планах статья о JSON-Schema (json-schema.org)? И парсинг json’a по этой схеме и создание POJO? Было бы очень круто)

было бы полезнее данный пример привести с методами, которые позволили бы читать json не из файла. К примеру, я работаю с бд, в которой сохраняю значения полей объекта в одном строковом поле. В таком случае мне больше подошла бы такая реализация: public String objectToJson(Object obj) throws JsonProcessingException <
String jsonObject = mapper.writeValueAsString(obj);
return jsonObject;
> public Object jsonToObject(String json) throws IOException <
Object obj = mapper.readValue(json, Sample.class);
return obj;
> где Sample – класс, с которым мы работаем. Затем, при вызове метода jsonToObject нам останется только привести полученный объект к нашему типу и делать с ним все, что угодно. Точно также дело обстоит с методом objectToJson – получаем чистую строку, с которой можем делать что угодно – писать в файл, в базу, выполнять манипуляции в коде и т.д. Я к тому, что такой пример был бы более абстрактен. Но в целом все отлично, мне нравятся ваши статьи

Евгений, полностью с вами согласен, но хотелось показать на примере файла, что бы новичкам было понятней.

А что будет если не добить Json нотации перед полями, класса, который мы собираемся переводить в json. И еще.. Корректно ли будет проводится конвертация встроенного класса, например Key или Location или DATATIME? Еще хотелось бы услышать про особенности использования библиотеки gson. Спасибо за доступную форму предоставления материала.

Без аннотаций вы скорее всего получите Exception но уже не помню, надо проверить, Да со встроеными классами это тоже должно нормально работать, но опять же давно делал и не могу сказать точно .

Исключений не будет, данные в любом случае попадут в файл, просто если не указать аннотацию над полем, то имя ключа в json будет соответствовать имени поля.

Источник

Converting Java objects to JSON with Jackson

My Question is: Are my classes correct? Which instance do I have to call and how that I can achieve this JSON output?

9 Answers 9

To convert your object in JSON with Jackson:

import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); String json = ow.writeValueAsString(object); 

Only thing is the String comes out escaped from the ObjectWriter. Use: new JSONObject(ow.writeValueAsString(msg)) if it’s being sent out via Web Services like RESTful.

what is the fully qualifies package of JSONObject ? I am not able to find it in jackson-databind libarary.

I know this is old (and I am new to java), but I ran into the same problem. And the answers were not as clear to me as a newbie. so I thought I would add what I learned.

I used a third-party library to aid in the endeavor: org.codehaus.jackson All of the downloads for this can be found here.

For base JSON functionality, you need to add the following jars to your project’s libraries: jackson-mapper-asl and jackson-core-asl

Choose the version your project needs. (Typically you can go with the latest stable build).

Once they are imported in to your project’s libraries, add the following import lines to your code:

 import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.map.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; 

With the java object defined and assigned values that you wish to convert to JSON and return as part of a RESTful web service

User u = new User(); u.firstName = "Sample"; u.lastName = "User"; u.email = "sampleU@example.com"; ObjectMapper mapper = new ObjectMapper(); try < // convert user object to json string and return it return mapper.writeValueAsString(u); >catch (JsonGenerationException | JsonMappingException e) < // catch various errors e.printStackTrace(); >

The result should looks like this:

Источник

Читайте также:  Scheduled threads in java
Оцените статью