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 . |