JSON — це текстовий формат даних, заснований на JavaScript. Такий формат даних часто використовується для інтеграцій з зовнішніми сервісами або використовується для спілкування різних модулів програми. Тому кожному програмісту важливо знати, як працювати з таким форматом даних.
Робота з JSON складається з процесів:
Сериалізація — коли ми конвертуємо наші дані в JSON.
Десериалізація — коли з JSON рядки отримуємо POJO об'єкт.
Для зручної, швидкої та комфортної роботи існує безліч бібліотек, таких як Gson, Jackson і т.д. В даному уроці ми розглянемо роботу з Jackson.
Для цього нам необхідно додати наступну залежність в наш pom.xml файл.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.4</version>
</dependency>
Сериалізація
Для кращого розуміння розглянемо приклад простої програми:
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);