Вступление
Формат JSON - один из самых популярных способов сериализации данных. Умение читать и писать - важный навык для любого программиста. Есть несколько библиотек Java, которые могут анализировать JSON, но в этом руководстве мы сосредоточимся на проекте с открытым исходным кодом, разработанном Google, который называется GSON.
GSON - это легкая библиотека Java, которая обеспечивает функции сериализации / десериализации. Что отличает GSON от других, так это его поддержка универсальных типов , которая ограничена некоторыми, но не всеми альтернативными библиотеками.
Примечание. Если вы не знакомы с универсальными шаблонами и почему это так важно, не стесняйтесь читать наше Руководство по пониманию универсальных шаблонов Java .
Поскольку мы работаем с внешней библиотекой, давайте добавим зависимость. Если вы используете Maven, вы можете добавить его с помощью:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${version}</version>
</dependency>
Или, если вы используете Gradle, вы можете добавить:
compile group: 'com.google.code.gson', name: 'gson', version: ${version}
Создание настраиваемого класса
Давайте создадим собственный класс, который мы сначала сериализуем в
JSON, а затем десериализуем из JSON - Student
:
public class Student {
private String firstName;
private String lastName;
private int studentID;
private String email;
private List<String> courses;
private FINANCE_TYPE financeType;
// Getters, setters, constructor, toString()
}
Для нашего Student
у нас дополнительно есть перечисление,
показывающее, есть ли у них бюджет ( SUBSIDIZED
) или нет (
UNSUBSIDIZED
):
public enum FINANCE_TYPE {
SUBSIDIZED, UNSUBSIDIZED
}
Преобразование объекта Java в объект JSON с помощью GSON
Теперь, когда мы определили наш класс, давайте создадим его экземпляр и
сериализуем его в эквивалентное ему представление JSON. Мы сделаем это с
помощью метода toJson()
который принимает объект в качестве аргумента
и возвращает JSON-представление этого объекта:
// Defining courses
List<String> physicsCourses = Arrays.asList("Physics 8.01", "Physics 8.012");
List<String> musicCourses = Arrays.asList("Jazz", "Blues");
// Instantiating students
Student max = new Student("Max", "Tegmark", 1254, " [email protected] ", physicsCourses, FINANCE_TYPE.SUBSIDIZED);
Student amy = new Student("Amy", "Winehouse", 1328, " [email protected] ", musicCourses, FINANCE_TYPE.SUBSIDIZED);
// Instantiating Gson
Gson gson = new Gson();
// Converting POJO to JSON
String maxJson = gson.toJson(max);
String amyJson = gson.toJson(amy);
System.out.println(maxJson);
System.out.println(amyJson);
Это преобразует наши POJO в строки JSON, которые при печати приводят к:
{"firstName":"Max","lastName":"Tegmark","studentID":1254,"email":" [email protected] ","courses":["Physics 8.01","Physics 8.012"],"financeType":"SUBSIDIZED"}
{"firstName":"Amy","lastName":"Winehouse","studentID":1328,"email":" [email protected] ","courses":["Jazz","Blues"],"financeType":"SUBSIDIZED"}
Преобразование строки JSON в объект Java
Чтобы отменить этот процесс и сопоставить объект JSON с POJO, мы будем
использовать метод fromJson()
. Он принимает строку JSON или
Reader
и класс или TypeToken
.
Давайте сначала посмотрим на первое:
String maxJson = "{\"firstName\":\"Max\",\"lastName\":\"Tegmark\",\"studentID\":1254,\"email\":\" [email protected] \",\"courses\":[\"Physics 8.01\",\"Physics 8.012\"],\"financeType\":\"SUBSIDIZED\"}";
Gson gson = new Gson();
Student max = gson.fromJson(maxJson, Student.class);
System.out.println(max);
Это создает экземпляр max
и заполняет его данными из объекта JSON:
Student{firstName='Max', lastName='Tegmark', studentID=1254, email=' [email protected] ', courses=[Physics 8.01, Physics 8.012], financeType=SUBSIDIZED}
Преобразование файла JSON в объект Java
Теперь мы можем не работать с JSON в формате String - нам часто
приходится читать файлы JSON. Метод fromJson()
принимает Reader
,
который мы также можем использовать для предоставления данных JSON.
Давайте переместим данные Эми в файл amy.json
{
"firstName":"Amy",
"lastName":"Winehouse",
"studentID":1328,
"email":" [email protected] ",
"courses":[
"Jazz",
"Blues"
],
"financeType":"SUBSIDIZED"
}
Теперь мы можем использовать Reader
, например FileReader
для чтения
этого файла и использовать его для ввода вместо String. Кроме того,
вместо использования Student.class
мы предоставляем Type
. Этот
Type
извлекается из Gson в TypeToken
, что значительно аналогично
Джексона TypeReference
:
// Instantiate FileReader for amy.json
Reader input = new FileReader("./src/main/resources/amy.json");
//Instantiate Gson
Gson gson = new Gson();
// Create a Type via TypeToken for the Student class
Type type = new TypeToken<Student>(){}.getType();
// Read the `input` and cast into `type`
Student amy = gson.fromJson(input, type);
// Print result
System.out.println(amy);
Это, конечно же, также создает и заполняет наш POJO Student
Student{firstName='Amy', lastName='Winehouse', studentID=1328, email=' [email protected] ', courses=[Jazz, Blues], financeType=SUBSIDIZED}
Компактная и красивая печать
По умолчанию GSON печатает JSON в компактном формате, который мы уже видели ранее:
{"firstName":"Max","lastName":"Tegmark","studentID":1254,"email":" [email protected] ","courses":["Physics 8.01","Physics 8.012"],"financeType":"SUBSIDIZED"}
{"firstName":"Amy","lastName":"Winehouse","studentID":1328,"email":" [email protected] ","courses":["Jazz","Blues"],"financeType":"SUBSIDIZED"}
Между именами полей и их значениями, полями объектов и объектами в
массивах нет пробелов. Кроме того, нет ни одной новой строки . Если
скопировать как String - \n
(новые строки) будут присутствовать, это
компактное представление затруднительно для чтения.
Мы можем довольно легко включить красивую печать с помощью Gson. При
Gson
экземпляра Gson вместо вызова пустого конструктора по умолчанию
мы можем использовать конструктор GsonBuilder()
:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Теперь мы можем использовать gson
почти так же, как и раньше:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String amyJson = gson.toJson(amy);
System.out.println(amyJson);
Хотя, на этот раз, при печати - строка JSON имеет довольно печать включена:
{
"firstName": "Amy",
"lastName": "Winehouse",
"studentID": 1328,
"email": " [email protected] ",
"courses": [
"Jazz",
"Blues"
],
"financeType": "SUBSIDIZED"
}
Именование полей JSON с помощью @SerializedName
Сериализация обычно используется для передачи данных между службами, в первую очередь через REST API. При работе с различными службами, командами или даже языками, которые обрабатывают данные, которые мы предоставляем, мы можем захотеть изменить сериализованные имена определенных полей, чтобы они соответствовали более широко принятым стандартам или стандартам определенной службы, которая будет обрабатывать предоставленные нами данные.
Например, мы могли бы предоставлять данные JSON из службы Java в службу
Python. Соглашения об именах в Java соответствуют CamelCase , в то
время как соглашения об именах в Python соответствуют нижнему
lowercase_with_underscores
для неконстант и классов.
Зная, что мы будем предоставлять наши данные службе или человеку,
который может захотеть использовать другие соглашения, мы можем изменить
сериализованные имена наших полей, чтобы они не совпадали с именами в
нашем POJO, через аннотацию @SerializedName
public class Student {
@SerializedName("first_name")
private String firstName;
@SerializedName("last_name")
private String lastName;
@SerializedName("student_id")
private int studentID;
@SerializedName("student_email")
private String email;
@SerializedName("student_courses")
private List<String> courses;
@SerializedName("student_finance_type")
private FINANCE_TYPE financeType;
// Getters, setters, constructor, toString()
}
Теперь при сериализации эти имена будут использоваться вместо имен наших полей:
String amyJson = gson.toJson(amy);
System.out.println(amyJson);
Что приводит к:
{
"first_name": "Amy",
"last_name": "Winehouse",
"student_id": 1328,
"student_email": " [email protected] ",
"student_courses": [
"Jazz",
"Blues"
],
"student_finance_type": "SUBSIDIZED"
}
Это также работает и наоборот - если мы получим JSON с first_name
а
наш POJO Student
first_name
сопоставленный с firstName
, мы
десериализуем это просто отлично:
String input = "{\"first_name\":\"Amy\",\"last_name\":\"Winehouse\",\"student_id\":1328,\"student_email\":\" [email protected] \",\"student_courses\":[\"Jazz\",\"Blues\"],\"student_finance_type\":\"SUBSIDIZED\"}";
Gson gson = new Gson();
Student amy = gson.fromJson(input, Student.class);
System.out.println(amy);
Это приводит к:
Student{firstName='Amy', lastName='Winehouse', studentID=1328, email=' [email protected] ', courses=[Jazz, Blues], financeType=SUBSIDIZED}
Заключение
В этом руководстве мы рассмотрели, как преобразовать объект Java в
объект JSON с помощью метода Gson toJson()
, а также как преобразовать
объект JSON в объект Java с помощью метода fromJson()
.
Мы также изучили, как включить красивую печать, а также изменить сериализованные имена полей.