dartlang convert json dart

convert - json flutter



¿Agregar serializador JSON a cada clase de modelo? (7)

Escribí la biblioteca Exportable para resolver cosas como convertir a Map o JSON. Utilizándolo, la declaración del modelo se ve así:

import ''package:exportable/exportable.dart''; class Customer extends Object with Exportable { @export int id; @export String name; }

Y si quiere convertir a JSON, puede:

String jsonString = customer.toJson();

Además, es fácil inicializar un nuevo objeto a partir de una cadena JSON:

Customer customer = new Customer()..initFromJson(jsonString);

O alternativamente:

Customer customer = new Exportable(Customer, jsonString);

Por favor, vea el Exportable para más información.

Cuando se trata de la codificación JSON en Dart, por consigna de Seth Ladd, la forma finalmente aprobada ahora oficial es dart:convert + JSON.Encode .

Digamos que tenemos un grupo de clases modelo ( PODO ) tales como:

class Customer { int Id; String Name; }

Ahora, me encantaría poder solo codificar JSON mis objetos de dominio de esta manera:

var customer = new Customer() ..Id = 17 ..Name = "John"; var json = JSON.encode(customer);

Lamentablemente, esto no funcionará ...

Uncaught Error: Converting object to an encodable object failed. Stack Trace: #0 _JsonStringifier.stringifyValue (dart:convert/json.dart:416) #1 _JsonStringifier.stringify (dart:convert/json.dart:336) #2 JsonEncoder.convert (dart:convert/json.dart:177) ....

... a menos que explícitamente le digamos a dart:convert cómo codificar:

class Customer { int Id; String Name; Map toJson() { Map map = new Map(); map["Id"] = Id; map["Name"] = Name; return map; } }

¿Realmente tengo que agregar un método toJson a cada una de mis clases modelo, o hay una mejor manera?

EDITAR : esta es la serialización simple que estoy buscando:

{ "Id": 17, "Name": "John" }

Compare con ToJson en ServiceStack.Text , por ejemplo.

La biblioteca de serialization de Dart (vea la respuesta de Matt B a continuación) parece un paso en la dirección correcta. Sin embargo, esto ...

var serialization = new Serialization() ..addRuleFor(Customer); var json = JSON.encode(serialization.write(customer, format: new SimpleJsonFormat()));

... produce solo una matriz con los valores (sin teclas):

[17,"John"]

El uso del SimpleMapFormat predeterminado, por otro lado, genera esta representación complex .

Todavía no he encontrado lo que estoy buscando ...

EDIT 2 : Añadiendo algo de contexto: estoy construyendo un servicio web RESTful en Dart, y estoy buscando una serialización JSON que pueda ser consumida fácilmente por cualquier cliente, no solo por otro cliente Dart. Por ejemplo, consultar la API Stack Exchange para esta misma pregunta creará esta respuesta JSON . Este es el formato de serialización que estoy buscando. - O bien, mire las respuestas típicas de JSON devueltas por la API REST de Twitter o la API Graph de Facebook .

EDIT 3 : escribí una pequeña publicación de blog sobre esto. Ver también la discussion sobre Hacker News.


IMO: este es uno de los principales cortos en Dart, sorprendente dado su enfoque en la Aplicación Web. Pensé que tener soporte para JSON en las bibliotecas estándar habría significado que la serialización de clases desde y hacia JSON funcionaría como agua. Desafortunadamente, la compatibilidad con JSON parece incompleta, donde parece que las opciones son trabajar con mapas sueltos o sufrir a través de una repetición innecesaria para configurar sus clases estándar (PODO) para serializar como se esperaba.

Sin el soporte Reflection and Mirrors

Como las plataformas populares de Dart como Flutter no son compatibles con Reflection / Mirrors, su única opción es utilizar una solución de código genérico. El enfoque que hemos adoptado en el soporte nativo de ServiceStack para Dart y Flutter le permite generar modelos Dart tipados para todos sus Servicios ServiceStack desde una URL remota, por ejemplo:

$ npm install -g @servicestack/cli $ dart-ref https://www.techstacks.io

Compatible con .NET Core y cualquiera de las populares opciones de alojamiento de .NET .

El ejemplo anterior genera una API Typed para el proyecto .NET Core 2.0 TechStacks utilizando los DTO generados desde www.techstacks.io/types/dart endpoint. Esto genera modelos siguiendo el patrón JsonCodec de Dart, donde puede personalizar la serialización para sus modelos Dart proporcionando un constructor nombrado por fromJson y un método de instancia toJson() , aquí hay un ejemplo de uno de los DTO generados:

class UserInfo implements IConvertible { String userName; String avatarUrl; int stacksCount; UserInfo({this.userName,this.avatarUrl,this.stacksCount}); UserInfo.fromJson(Map<String, dynamic> json) { fromMap(json); } fromMap(Map<String, dynamic> json) { userName = json[''userName'']; avatarUrl = json[''avatarUrl'']; stacksCount = json[''stacksCount'']; return this; } Map<String, dynamic> toJson() => { ''userName'': userName, ''avatarUrl'': avatarUrl, ''stacksCount'': stacksCount }; TypeContext context = _ctx; }

Con este modelo, puede utilizar las API json: convert de Dart para serializar y deserializar su modelo a JSON, por ejemplo:

//Serialization var dto = new UserInfo(userName:"foo",avatarUrl:profileUrl,stacksCount:10); String jsonString = json.encode(dto); //Deserialization Map<String,dynamic> jsonObj = json.decode(jsonString); var fromJson = new UserInfo.fromJson(jsonObj);

El beneficio de este enfoque es que funciona en todas las plataformas de Dart , incluidas las aplicaciones web Flutter y AngularDart o Dart con y sin el modo fuerte de Dart 2.

Los DTO generados también se pueden usar con el paquete Dart de servicestack para permitir una solución tipeada de extremo a extremo que tenga en cuenta la serialización JSON dentro y fuera de los DTOs escritos, por ejemplo:

var client = new JsonServiceClient("https://www.techstacks.io"); var response = await client.get(new GetUserInfo(userName:"mythz"));

Para obtener más información, consulte los documentos del soporte Dart nativo de ServiceStack .

Dart con espejos

Si está utilizando Dart en una plataforma donde está disponible el soporte de Mirrors, he encontrado que usar Mixin requiere el menor esfuerzo, por ejemplo:

import ''dart:convert''; import ''dart:mirrors''; abstract class Serializable { Map toJson() { Map map = new Map(); InstanceMirror im = reflect(this); ClassMirror cm = im.type; var decls = cm.declarations.values.where((dm) => dm is VariableMirror); decls.forEach((dm) { var key = MirrorSystem.getName(dm.simpleName); var val = im.getField(dm.simpleName).reflectee; map[key] = val; }); return map; } }

Que puedes mezclar con tus clases de PODO con:

class Customer extends Object with Serializable { int Id; String Name; }

Que ahora puedes usar con JSON.encode :

var c = new Customer()..Id = 1..Name = "Foo"; print(JSON.encode(c));

Resultado:

{"Id":1,"Name":"Foo"}

Nota: ver advertencias con el uso de espejos


Lo he resuelto con:

class Customer extends JsonObject { int Id; String Name; Address Addr; } class Address extends JsonObject{ String city; String State; String Street; }

Pero mi objetivo es vincular datos de / a json desde / a las clases modelo; Esta solución funciona si puede modificar las clases de modelo, en un contraste debe usar la solución "externa" para convertir clases de modelo;

ver también: Análisis de la lista JSON con la biblioteca JsonObject en Dart


Otro paquete que soluciona este problema es built_value:

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

Con built_value tus clases modelo se ven así:

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._(); }

Tenga en cuenta que built_value no se trata solo de serialización, sino que también proporciona operador ==, hashCode, toString y una clase de generador.


Una alternativa es usar el paquete de serialización y agregar reglas para sus clases. La forma más básica usa la reflexión para obtener las propiedades automáticamente.


Utilicé Dartson y me parece muy fácil y familiar (si vienes de Java)


Redstone mapper es la mejor biblioteca de serialización que he usado. JsonObject y Exportable tienen la desventaja de que tienes que extender algunas de sus clases. Con Redstone Mapper puedes tener estructuras como esta

class News { @Field() String title; @Field() String text; @Field() List<FileDb> images; @Field() String link; }

Funciona con getters y setters, puede ocultar información al no @Field() con @Field() , puede cambiar el nombre de campo de / a json, tiene objetos anidados, funciona en el servidor y el cliente. También se integra con el marco del Servidor Redstone, donde tiene ayudantes para codificar / decodificar a MongoDB.

El único otro marco que he visto que está en la dirección correcta es Dartson , pero aún le faltan algunas características en comparación con Redstone Mapper.