JSON & GWT
Недавно в группе пользователей GWT прошла интересная дискуссия о передовых методах сериализации / десериализации JSON на стороне клиента. Этот пост призван подчеркнуть его важные моменты. До сих пор существует три различных способа преобразования объекта в JSON и обратно со стороны клиента в GWT:
GWT-Джексон рамки:
gwt-jackson оборачивает некоторые функции знаменитой библиотеки Джексона . Это позволяет конвертировать объект, используя интерфейс под названием ObjectMapper . Преимущество использования gwt-jackson заключается в том, что он заботится о сериализации сложных объектов, таких как коллекции и карты. Это также позволяет модное преобразование, используя аннотации, такие как @JsonProperty и @JsonCreator. Единственный недостаток gwt-jackson в том, что он использует генераторы, которые будут устаревшими в версии 3.0 GWT. Также стоит отметить, что gwt- jackson используется RestyGWT, который является одной из альтернатив для выполнения HTTP-запросов со стороны клиента.
Примеры можно найти на странице Github: https://github.com/nmorel/gwt-jackson/tree/master/examples
используя JavaScriptObject:
Это один из традиционных методов. JavaScriptObject использует JSNI для создания простого объекта JS. Он может быть расширен и имеет метод cast (), который позволяет «безопасно» приводить объект к его подтипам. JavaScriptObject может быть преобразован в строку JSON с помощью метода JsonUtils.stringify () и обратно с помощью JsonUtils.safeEval (). JavaScriptObject работает в сочетании с JsArray, который представляет собой коллекцию JavaScriptObject и расширяет JavaScriptObject. Единственным недостатком этого метода является шаблон, связанный с созданием объектов. Например:
|
01
02
03
04
05
06
07
08
09
10
11
|
public class Person extends JavaScriptObject { //Constructor needs to be protected and zero-arguments protected Person() { } // JSNI is used for setting/getting properties public final native String getFirstName() /*-{ return this.FirstName; }-*/; public final native String getLastName() /*-{ return this.LastName; }-*/; public final native void setFirstName(String firstName) /*-{ this.FirstName = firstName; }-*/; public final native void setLastName(String lastName) /*-{ this.LastName = lastName; }-*/;} |
Потом:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
Person person = JavaScriptObject.createObject().cast(); JsArray array = JavaScriptObject.createArray().cast(); person.setFirstName("first Name"); person.setLastName("last Name"); array.push(person); GWT.log(JsonUtils.stringify(person)); GWT.log(JsonUtils.stringify(array)); |
Результат:
|
1
2
|
{"FirstName":"first Name","LastName":"last Name"}[{"FirstName":"first Name","LastName":"last Name"}] |
используя аннотации JsInterop:
Аннотации JsInterop позволяют рассматривать тип / класс java как объект Javascript, а также экспортировать или импортировать функциональные возможности в / из среды Js приложения. Использование JsInterop является рекомендуемым методом для некоторых участников проекта GWT ( Томас Бройер , Дженс Нельмейер ), потому что JsInterop является важной частью будущего GWT и будет основным способом обработки объектов Javascript из GWT. Единственным недостатком использования JsInterop является то, что Elemental 2 все еще находится в экспериментальной фазе, поэтому пока не станет стабильным. Разработчикам лучше использовать свои собственные фрагменты для собственных утилит Javascript, таких как класс Json, например:
|
1
2
3
4
5
6
7
8
|
@JsType(isNative=true, namespace=GLOBAL)public class JSON { public native static String stringify(Object obj); public native static Object parse(String obj);} |
если наш объект выглядит так:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
@JsType(isNative=true, namespace=GLOBAL, name="Object")public class Record { String id; String date; String data; public Record() { } } |
Потом :
|
1
2
3
4
5
6
7
8
9
|
Record record = new Record(); record.id = "1"; record.date = "20"; record.data = "30";String json = JSON.stringify(recod); GWT.log(json);// Result: {"id":"1","date":"20","data":"30"} |
JsInterop используется autorest -gwt , который также является одним из вариантов выполнения HTTP-вызовов, для сериализации / сериализации объектов перед выполнением HTTP-запросов.
Важно отметить, что Карты не обрабатываются методом JSON.stringify (), попытка строкового преобразования Карты приводит к следующей ошибке:
|
1
2
3
4
|
Map mapTest = new HashMap(); mapTest.put("v1", "v2"); mapTest.put("v3", "v4"); GWT.log(JSON.stringify(mapTest)); |
|
1
|
Uncaught TypeError: Converting circular structure to JSON |
Преобразование коллекции, такой как ArrayList, не выдает никакой ошибки, но создает дополнительные поля JSON, от которых разработчик захочет избавиться:
|
1
2
3
4
5
|
List test2 = new ArrayList(); test2.add(record2); test2.add(record); GWT.log(JSON.stringify(test2)); |
Результат:
|
1
|
{"array_3_g$":[{"id":"1","date":"50","data":"90"},{"id":"1","date":"20","data":"30"}]} |
«Массив_3_g $» по какой-то причине добавлен компилятором GWT, поэтому пользователю нужно найти способ удалить его для чистого преобразования, например:
|
1
|
{[{"id":"1","date":"50","data":"90"},{"id":"1","date":"20","data":"30"}]} |
Plain Arrays — пока единственная структура, которая правильно преобразована.
Увезти
Из трех методов JsInterop представляется наиболее жизнеспособным методом обработки JSON. На данный момент основной задачей является обработка таких объектов, как Коллекции и Карты, которые требуют дальнейшей ручной обработки разработчиком. Простые массивы — единственная структура, которая на данный момент правильно преобразована, поэтому разработчики могут попытаться упростить или преобразовать в простые массивы для чистого преобразования.
В то время как JavaScriptObject предлагает свой собственный способ работы со «списками» с использованием JsArray. Теперь gwt-jackson остается единственным вариантом, который предлагает конвертацию коллекций и карт из коробки.
| Ссылка: | Сериализация / десериализация Json в GWT от нашего партнера по JCG Закарии Амине в блоге G-Widgets . |