JSON — это текстовый формат данных, основанный на JavaScript. Такой формат данных часто используется для интеграций с внешними сервисами или используется для общения различных модулей приложения, поэтому каждому программисту важно знать, как работать с таким форматом данных.
Работа с JSON состоит из процессов сериализации и десериализации. Это означает следующее:
- Сериализации — когда мы конвертируем наши данные в JSON
- Десериализации — когда из JSON строки получаем POJO объект
Для удобной, быстрой и комфортной работы существует множество библиотек, таких как Gson, Jackson и т.д. В этой статье мы рассмотрим работу с Jackson, JSON сериализацию и десериализацию.
Для этого нам необходимо добавить следующую зависимость в наш pom.xml файл.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.4</version>
</dependency>
Сериализация Java
Для лучшего понимания рассмотрим пример простой программы:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Arrays;
import java.util.List;
public class SerializationExample {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Certificate certificateOracle = new Certificate();
certificateOracle.name = "ORACLE";
certificateOracle.year = 2000;
Certificate certificateSun = new Certificate();
certificateSun.name = "SUN";
certificateSun.year = 2015;
Department department = new Department();
department.setName("Computer Science");
Student student = new Student();
student.id = 2;
student.department = department;
student.name = "Ali Z";
student.certificates = Arrays.asList(certificateOracle, certificateSun);
String json = objectMapper.writeValueAsString(student);
System.out.println(json);
}
static class Student {
private int id;
private String name;
@JsonProperty("dep")
private Department department;
private List<Certificate> certificates;
public List<Certificate> getCertificates() {
return certificates;
}
public void setCertificates(List<Certificate> certificates) {
this.certificates = certificates;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
@Override
public String toString() {
return "Student{"
+ "name='" + name + '\'' + ", id='" + id + '\''
+ '}';
}
}
static class Department {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
static class Certificate {
private String name;
private int year;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
Результатом этой программы будет следующая строка:
{
"id" : 2,
"name" : "Ali Z",
"certificates" : [ {
"name" : "ORACLE",
"year" : 2000
}, {
"name" : "SUN",
"year" : 2015
} ],
"dep" : {
"name" : "Computer Science"
}
}
В этом примере у нас есть следующие сущности (POJO объекты):
Student — класс, который описывает студента.
id — уникальный номер каждого студента.
name — имя нашего студента.
Department — описывает факультет, на котором обучается наш студент.
Certificate — грамоты и награды, которые получил наш студент.
По умолчанию, если мы никак не аннотируем класс, то Jackson даст JSON поле название переменной. Для того, чтобы наше JSON поле имело другое название, необходимо использовать аннотацию @JsonProperty, где в качестве параметра передать название.
Jackson также может сериализовать List объектов в массива JSON.
Десериализация в Jackson
Попробуем десериализовать следующую JSON строку:
{"id":2,"name":"Ali Z","certificates":[{"name":"ORACLE","year":2000},{"name":"SUN","year":2015}]}
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
public class DeserializationExample {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
String json = "{\"id\":2,
\"name\":\"Ali Z\"," +
"\"certificates\":[" +
"{\"name\":\"ORACLE\",\"year\":2000}," +
"{\"name\":\"SUN\",\"year\":2015}" +
"]" +
"}";
Student student = objectMapper.readValue(json, Student.class);
System.out.println(student);
}
@JsonIgnoreProperties(ignoreUnknown = true)
static class Student {
private int id;
private String name;
@JsonProperty("dep")
private Department department;
private List<Certificate> certificates;
public List<Certificate> getCertificates() {
return certificates;
}
public void setCertificates(List<Certificate> certificates) {
this.certificates = certificates;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
@Override
public String toString() {
return "Student{"
+ "name='" + name + '\'' + ", id='" + id + '\''
+ '}';
}
}
static class Department {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
static class Certificate {
private String name;
private int year;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
Как вы заметили, наш JSON не содержит информации по отделению студента, для того, чтобы Jackson не выдавал ошибку при десериализации JSON, необходимо пометить класс аннотацией @JsonIgnoreProperties(ignoreUnknown = true), или же задать глобальную конфигурацию следующим образом:
ObjectMapper objectMapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false);