Статьи

Сериализация / десериализация Json в GWT

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 .