2014-11-25 5 views
3

У меня был хороший опыт сериализации на C#, и после поиска и тестирования некоторых библиотек Дарта я чувствую, что в целом нет удовлетворительного ответа.Состояние сериализации и десериализации JSON в Dart

  1. Id нравится знать текущее состояние сериализации/десериализации JSON в Dart?
  2. Что мы должны ожидать в будущем?
  3. Будет ли это в конечном итоге поддержано самим языком?
  4. Какие в настоящее время лучшие практики?

Id также как и любой, кто читает это, чтобы опубликовать любую новую информацию, даже если сообщение стареет.

+0

Что вы подразумеваете под «Сериализация/десериализация JSON в дарте»? – Robert

+0

Это зависит от ваших потребностей. –

+0

Сериализация * * JSON проста - JSON - это текстовый формат. Я предполагаю, что вы хотите сериализацию объектов Дарта в JSON и десериализацию от JSON. Это вызывает вопрос: почему важно, чтобы формат сериализации был JSON? Dart имеет JSON-кодирование данных «JSON-like» (num, string, bool, null, List и Map ), но JSON-кодирование не является сериализацией. Существуют библиотеки сериализации, но они могут иметь или не иметь основанный на JSON сериализованный формат (ну, единственная String будет JSON, но это, вероятно, не то, о чем вы думаете) – lrn

ответ

4

На данный момент лучшим вариантом является, вероятно, использование библиотеки Smoke.

Это подмножество функциональности Зеркала, но имеет как реализацию на основе зеркал, так и реализацию на основе кодека. Это написано командой PolymerDart, поэтому он близок к «Официальному», как мы собираемся получить.

При разработке он будет использовать кодировку/декодирование на основе зеркал; но для публикации вы можете создать небольшой трансформатор, который будет генерировать код.

Сет Лэдд создал a code sample here, который я extended slightly для поддержки детей-объекты: (., Например, для поддержки списка)

abstract class Serializable { 
    static fromJson(Type t, Map json) { 
    var typeMirror = reflectType(t); 
    T obj = typeMirror.newInstance(new Symbol(""), const[]).reflectee; 
    json.forEach((k, v) { 
     if (v is Map) { 
     var d = smoke.getDeclaration(t, smoke.nameToSymbol(k)); 
     smoke.write(obj, smoke.nameToSymbol(k), Serializable.fromJson(d.type, v)); 
     } else { 
     smoke.write(obj, smoke.nameToSymbol(k), v); 
     } 
    }); 
    return obj; 
    } 

    Map toJson() { 
    var options = new smoke.QueryOptions(includeProperties: false); 
    var res = smoke.query(runtimeType, options); 
    var map = {}; 
    res.forEach((r) => map[smoke.symbolToName(r.name)] = smoke.read(this, r.name)); 
    return map; 
    } 
} 

В настоящее время нет никакой поддержки, чтобы получить общую информацию о типе в дым; Однако я поднял дело об этом здесь:

https://code.google.com/p/dart/issues/detail?id=20584

Пока этот вопрос не будет реализован, «хороший» осуществление того, что вы хотите на самом деле не представляется возможным; но я надеюсь, что это будет реализовано в ближайшее время; потому что выполнение чего-то основного, как JSON-сериализация, зависит от этого!

Alan Knight также работает над пакетом Serialization, однако я обнаружил, что ему не хватает поддержки так же просто, как преобразование datetimes в строки, и решение казалось довольно многословным для чего-то такого основного.

Пока что в моем собственном проекте я пошел с кодированием нашей сериализации json (в форме методов toMap и fromMap), так как у нас уже были бы версии C# наших классов для серверной части. Если позволяет время, я бы хотел привести в порядок этот код и сделать пакет NuGet (он поддерживает вложенные объекты, массивы, исключая свойства и т. Д.).

+0

Может ли дочерний объект также иметь дочерний объект, если нет циклов? –

+0

Реализация Codegen не подходит в большинстве случаев, потому что это необходимое преобразование кода, которое не является лучшим решением. – mezoni

+0

В дыме? Или мой C#? Мой C# будет делать любое количество уровней, это просто для карты/с карты, и использует встроенный кодер JSON, хотя я не уверен, как это обрабатывает циклы. –

2

В настоящее время вы можете использовать redstone_mapper, чтобы конвертировать объекты Dart в JSON. Этот пакет является плагином для рамки Redstone.dart, но может использоваться без него.Существуют также другие варианты на Pub

+0

. Сериализует/десериализует вложенные объекты? –

+0

Да, да. Вы также можете использовать вложенные списки и карты. – luizmineo

0

Dart имеет реализацию для кодирования и декодирования карт, списков и примитивных типов. Вы можете найти примеры на this article. Если вы ищете скорость, это, вероятно, самый быстрый, поскольку они реализуют json-преобразование в родных C/C++ - библиотеки, созданные авторами, обычно записываются в Dart и будут медленнее.

Недостатком JSON.encode и JSON.decode является то, что они не могут принимать какие-либо другие объекты, кроме упомянутых выше, без методов toJson и fromJson.

К счастью, есть библиотеки, которые используют отражение в Дарте, чтобы сделать его проще. Я сам создал небольшую библиотеку, чтобы сериализовать и десериализовать объекты в JSON и из него без дополнительного кода для ваших классов. Вы можете найти его here. В дополнение к вышеупомянутым решениям по вашей проблеме, вы можете найти много на сайте Dart pub.

1

Как правило, переход от зеркальных решений к решениям на основе кодеков, в частности, основан на пакете: source_gen. Это связано с тем, что codegen может предоставлять меньше и быстрее время автономной работы, чем зеркала.

Один пакет, который использует CodeGen для сериализации built_value:

https://github.com/google/built_value.dart

С built_value классы моделей выглядеть следующим образом:

abstract class Account implements Built<Account, AccountBuilder> { 
    static Serializer<Account> get serializer => _$accountSerializer; 

    int get id; 
    String get name; 
    BuiltMap<String, JsonObject> get keyValues; 

    factory Account([updates(AccountBuilder b)]) = _$Account; 
    Account._(); 
} 

Обратите внимание, что built_value не только о сериализации - он также предоставляет оператор ==, hashCode, toString и класс строителя.

Смежные вопросы