01. Прошлая и настоящая жизнь
Меня зовут Gson, это библиотека Java с открытым исходным кодом, основной целью которой является сериализация объектов Java в строки JSON или десериализация строк JSON в объекты Java. Из моего имени вы можете увидеть некоторые подсказки. Я не неизвестный человек. Я из знатной семьи. Мой отец Google.
Конечно, как умный человек, я осознаю себя, в глазах папы я не самая яркая звезда.
Я попал в этот мир чисто случайно.Во всяком случае,об этом мне рассказывал мой папа.Он всегда говорил,что я подобрала его с реки,хотя я никогда в это не верила. За это я подтвердил маме, а она расхохоталась от уха до уха, сказав, что я слишком наивен.
Когда я вырос, мне нравилось путешествовать, поэтому я встретил много коллег, в том числеJacksonиFastjson.
Говоря о Джексоне, я всегда могу думать о Майкле Джексоне, короле поп-музыки, которого забрал Бог. У Джексона 6,1 тысячи звезд на GitHub, хотя у него не так много поклонников, как у меня, я очень уважаю его как парсер JSON по умолчанию в Spring Boot.
Fastjson родом с загадочного Востока.Хотя были обнаружены некоторые серьезные уязвимости, это не мешает ему стать самым популярным парсером JSON.У него больше поклонников, чем у меня, хотя у меня уже более 18К звезд.
Посторонние всегда говорят, что мы конкуренты, но я должен сказать им, что отношения между нами тремя настолько хороши, что мы носим почти одно и то же нижнее белье.
У каждого из нас есть свои сильные стороны, Джексон использует меньше памяти во время выполнения, Fastjson работает быстрее, а я могу обрабатывать произвольные объекты Java даже без исходного кода. Кроме того, моя поддержка дженериков также более дружелюбна.
02. Добавьте зависимости
Прежде чем использовать мой API, мне нужно сначала добавить себя в проект.Рекомендуются Maven и Gradle.
Мейвен:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
Грейдл:
dependencies {
implementation 'com.google.code.gson:gson:2.8.6'
}
PS: Gradle — это инструмент построения автоматизации проектов, основанный на концепциях Apache Ant и Apache Maven. Сценарии сборки Gradle написаны на доменном языке Groovy или Kotlin, а не на традиционном XML.
03. Производительность
Это не то, что я думаю, это правда, с помощью множества тестов я доказал, что производительность по-прежнему очень хороша при работе с JSON.
Тестовая среда: двухъядерный процессор, 8 ГБ памяти, 64-битная операционная система Ubuntu (дистрибутив Linux на основе настольных приложений)
Результаты теста:
1) Не было проблем с десериализацией строк выше 25M.
2) Коллекция из 1,4 миллиона объектов может быть сериализована.
3) Коллекция, содержащая 87000 объектов, может быть десериализована.
4) Увеличьте предел десериализации для байтовых массивов и коллекций с 80K до более чем 11M.
Я написал для вас тестовый пример и выложил его на GitHub, если не верите, можете проверить.
04. Руководство пользователя
Не то чтобы я хвастаюсь, это правда, я до сих пор очень хорошо им пользуюсь, и сложность начала работы почти нулевая. Если не верите, можете попробовать.
У меня есть девушка, которую зовут так же, как и меня.Gson
, мои основные функции обеспечиваются ею. ты можешь пройтиnew Gson()
Это простой и грубый способ ее создания, вы также можете позвонить боссу по имени GsonBuilder и попросить его отправить копию по почте, правда, я не буду вам врать.
Давайте сначала рассмотрим пример сериализации.
Gson gson = new Gson();
System.out.println(gson.toJson(18));
System.out.println(gson.toJson("沉默"));
System.out.println(gson.toJson(new Integer(18)));
int[] values = { 18,20 };
System.out.println(gson.toJson(values));
С помощью моей подруги вы можете передать в качестве параметров примитивный тип данных int, строковый тип String, тип оболочки Integer, массив int и т. д.toJson()
метод, который вернет строку в формате JSON.
Взгляните на вывод:
18
"沉默"
18
[18,20]
Давайте снова посмотрим на пример десериализации.
Gson gson = new Gson();
int one = gson.fromJson("1", int.class);
Integer two = gson.fromJson("2", Integer.class);
Boolean false1 = gson.fromJson("false", Boolean.class);
String str = gson.fromJson("\"王二\"", String.class);
String[] anotherStr = gson.fromJson("[\"沉默\",\"王二\"]", String[].class);
System.out.println(one);
System.out.println(two);
System.out.println(false1);
System.out.println(str);
System.out.println(Arrays.toString(anotherStr));
toJson()
метод сериализации, соответствующий,fromJson()
способ десериализации. Однако вам необходимо указать тип параметра при десериализации, будь то int или Integer, Boolean или String или массив String.
Взгляните на вывод:
1
2
false
王二
[沉默, 王二]
Приведенные выше примеры относительно просты и не отражают моей силы.
Далее, давайте определим класс:
public class Writer {
private int age = 18;
private String name = "王二";
private transient int sex = 1;
}
Затем давайте сериализуем его:
Writer writer = new Writer();
Gson gson = new Gson();
String json = gson.toJson(writer);
System.out.println(json);
Использование так же просто, как и раньше, взгляните на результат:
{"age":18,"name":"王二"}
Точно так же результат можно десериализовать:
Writer writer1 = gson.fromJson(json, Writer.class);
Вот несколько предостережений, о которых я должен вам напомнить.
1) Рекомендуется использоватьprivate
Измененные поля.
2) Нет необходимости использовать какие-либо аннотации, чтобы указать, какие поля нужно сериализовать, а какие поля не нужно сериализовать. По умолчанию включаются все поля, а также поля, унаследованные от родительских классов.
3) Если полеtransient
Если ключевое слово изменено, оно не будет участвовать в сериализации.
4) Если значение поля равно null, оно не будет отображаться в сериализованном результате.
5) Отсутствующие поля в JSON будут установлены в значения по умолчанию после десериализации, значение по умолчанию для ссылочных типов данных — null, значение по умолчанию для числовых типов — 0, а значение по умолчанию для логических значений — false.
Далее рассмотрим пример сериализации коллекции.
List<String> list =new ArrayList<>();
list.add("好好学习");
list.add("天天向上");
String json = gson.toJson(list);
Результат выглядит следующим образом:
["好好学习","天天向上"]
При десериализации это также очень просто.
List<String> listResult = gson.fromJson(json,List.class);
Результат выглядит следующим образом:
[好好学习, 天天向上]
Моя девушка очень внимательный и заботливый человек, когда звонишьtoJson()
Когда метод будет сериализован, она сначала оценит значение null, чтобы предотвратить генерацию NPE, а затем передастgetClass()
Получите тип параметра, затем сериализуйте его.
public String toJson(Object src) {
if (src == null) {
return toJson(JsonNull.INSTANCE);
}
return toJson(src, src.getClass());
}
но? Для дженериков,getClass()
Параметризованный тип отбрасывается. Взгляните на пример ниже.
public class Foo<T> {
T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
public static void main(String[] args) {
Gson gson = new Gson();
Foo<Bar> foo = new Foo<Bar>();
Bar bar = new Bar();
foo.set(bar);
String json = gson.toJson(foo);
}
}
class Bar{
private int age = 10;
private String name = "图灵";
}
Если вы отлаживаете, перейдите кtoJson()
Внутри метода это можно наблюдать.
Фактический тип fooFoo<Bar>
, но моя девушка звонитfoo.getClass()
, получает только Foo , что означает, что она не знает фактический тип foo .
При сериализации все нормально, но при десериализации делать нечего.
Foo<Bar> foo1 = gson.fromJson(json, foo.getClass());
Bar bar1 = foo1.get();
Этот код выдает ошибку при запуске.
Exception in thread "main" java.lang.ClassCastException: class com.google.gson.internal.LinkedTreeMap cannot be cast to class com.itwanger.gson.Bar (com.google.gson.internal.LinkedTreeMap and com.itwanger.gson.Bar are in unnamed module of loader 'app')
at com.itwanger.gson.Foo.main(Foo.java:36)
По умолчанию тип параметра универсального типа будет преобразован в LinkedTreeMap, что явно не является тем Bar, которого мы ожидали, и подруга очень беспомощна в этом.
Как сын Гугла, слово "благородный" течет в моей крови, как я могу вынести одиночество своей девушки, когда она беспомощна.
Итак, я внедрил в тело своей девушки два других метода с параметрами Type:
toJson(Object src, Type typeOfSrc);
<T> T fromJson(String json, Type typeOfT);
Таким образом, вы можете указать параметризованный тип универсального типа при сериализации и десериализации универсального типа.
Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
String json = gson.toJson(foo,fooType);
Foo<Bar> foo1 = gson.fromJson(json, fooType);
Bar bar1 = foo1.get();
запись отладкиtoJson()
Если вы заглянете внутрь метода, то увидите настоящий тип foo.
fromJson()
Аналогично этому при десериализации.
В этом случае бар1 может пройтиfoo1.get()
прибыть.
Смотри, какой я задумчивый, моя девушка не может не сделать мне комплимент!
05. Работайте со смешанными типами
Вы знаете, Java не рекомендует использовать смешанные типы, как в случае ниже.
List list = new ArrayList();
list.add("沉默王二");
list.add(18);
list.add(new Event("gson", "google"));
Определение события выглядит так:
class Event {
private String name;
private String source;
Event(String name, String source) {
this.name = name;
this.source = source;
}
}
Поскольку список не определяет конкретный тип, в нем могут храниться различные типы данных. Хотя это избавляет от проблем, у моей подруги нет проблем с сериализацией, но с десериализацией будет больше проблем.
Gson gson = new Gson();
String json = gson.toJson(list);
System.out.println(json);
Результат выглядит следующим образом:
["沉默王二",18,{"name":"gson","source":"google"}]
При десериализации нужно подумать, чтобы получить объект Event.
JsonParser parser = new JsonParser();
JsonArray array = parser.parse(json).getAsJsonArray();
String message = gson.fromJson(array.get(0), String.class);
int number = gson.fromJson(array.get(1), int.class);
Event event = gson.fromJson(array.get(2), Event.class);
Признайтесь, JsonParser — мой предшественник. Надеюсь, ты не назовешь меня отморозком, это не потому, что я беспокоюсь, это потому, что мы немного не подходим друг другу. Но мы все равно остаемся друзьями, потому что никто из нас не прав, просто код более стандартизирован, и мало кто из разработчиков уже использует смешанные типы.
06. Индивидуальная настройка
Учитывая, что ты хипстер, я всегда была очень требовательна к себе и стремилась удовлетворить все твои потребности. Такой высокий стандарт заставляет мою девушку любить и ненавидеть меня.
Что мне нравится, так это мое стремление к совершенству; что я ненавижу, так это то, что она иногда перегружена и не может помочь.
использоватьtoJson()
При сериализации объекта Java возвращаемая строка JSON не содержит пробелов и является компактной. Если вы хотите напечатать более приятный формат JSON, вам нужно позвонить боссу по имени GsonBuilder и попросить его сделать некоторые настройки, а затем отправить вам переделку по почте, как я сделал вруководство пользователякак указано в.
public class Writer {
private int age = 18;
private String name = "沉默王二";
public static void main(String[] args) {
Writer writer = new Writer();
Gson gson = new Gson();
String json = gson.toJson(writer);
System.out.println(json);
Gson gson1 = new GsonBuilder().setPrettyPrinting().create();
String jsonOutput = gson1.toJson(writer);
System.out.println(jsonOutput);
}
}
Давайте сравним вывод:
{"age":18,"name":"沉默王二"}
{
"age": 18,
"name": "沉默王二"
}
пройти черезsetPrettyPrinting()
После настройки выходной формат становится более иерархическим и трехмерным, с пробелами между полями и значениями и разрывами строк между разными полями.
Как было сказано ранее, моя подруга по умолчанию игнорирует поля с нулевыми значениями при сериализации.Если вы этого не хотите, вы также можете вызвать GsonBuilder.
public class Writer {
private int age = 18;
private String name = null;
public static void main(String[] args) {
Writer writer = new Writer();
Gson gson = new Gson();
String json = gson.toJson(writer);
System.out.println(json);
Gson gson2 = new GsonBuilder().serializeNulls().create();
String jsonOutput2 = gson2.toJson(writer);
System.out.println(jsonOutput2);
}
}
Давайте сравним вывод:
{"age":18}
{"age":18,"name":null}
пройти черезserializeNulls()
После настройки поля с нулевыми значениями больше не будут игнорироваться при сериализации.
Возможно, вы хотите фильтровать какие-то поля при сериализации и десериализации, я тоже учёл это требование и специально для вас подготовил несколько решений, вы можете выбрать то, которое подходит вам по своему вкусу.
Первый, через модификатор Java.
Вы видели это раньше, используйтеtransient
Поля с измененным ключевым словом не будут участвовать в сериализации и десериализации. такой же,static
Так же как и поля, украшенные ключевыми словами. Если вы хотите сохранить эти поля, украшенные ключевыми словами, вы можете это сделать.
Держите один вид.
Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).create();
Держите разнообразие.
Gson gson = new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
.create();
Во-вторых, через@Expose
аннотация.
нужно использовать@Expose
аннотация, вам нужно сделать это в первую очередь:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Добавьте к полям, которые необходимо сериализовать и десериализовать@Expose
Аннотация, если не добавить, это поле будет проигнорировано.
@Expose
private int age = 18;
07. Голос
Если вы хотите узнать больше, посетите мою страницу GitHub:
Я открою вам все обо мне безоговорочно, за исключением некоторых секретов между мной и моей девушкой, просто чтобы помочь вам.
Если вы считаете, что я полезен, ставьте лайк, оставляйте комментарии, увидимся.
Рекомендуемое чтение:
Программист третьего уровня 2020, ни скромный, ни высокомерный | Ежегодное эссе Nuggets