Add JSON serializer to every model class?

前端 未结 9 1383
南旧
南旧 2020-11-28 07:56

When it comes to JSON encoding in Dart, per Seth Ladd\'s accouncement the finally approved now official way to go is dart:convert + JSON.Encode.

相关标签:
9条回答
  • 2020-11-28 08:32

    I prefer using https://ashamp.github.io/jsonToDartModel/ online tool write by myself.

    It has features below:

    • online use, without plugin
    • support multidimensional list
    • support complex json
    • support convert all props to String type
    • empty props warning
    • single file
    • dart keyword protected
    • instant convert

    I think it's better than other tools.Welcome if you have any suggestion, issue or bug report.

    0 讨论(0)
  • 2020-11-28 08:33

    IMO this is a major short-coming in Dart, surprising given its Web Application focus. I would've thought that having JSON support in the standard libraries would've meant that serializing classes to and from JSON would work like water, unfortunately the JSON support seems incomplete, where it appears the choices are to work with loosely typed maps or suffer through un-necessary boilerplate to configure your standard (PODO) classes to serialize as expected.

    Without Reflection and Mirrors support

    As popular Dart platforms like Flutter doesn't support Reflection/Mirrors your only option is to use a code-gen solution. The approach we've taken in ServiceStack's native support for Dart and Flutter lets you generate typed Dart models for all your ServiceStack Services from a remote URL, e.g:

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

    Supported in .NET Core and any of .NET's popular hosting options.

    The example above generates a Typed API for the .NET Core 2.0 TechStacks project using the generated DTOs from www.techstacks.io/types/dart endpoint. This generates models following Dart's JsonCodec pattern where you can customize serialization for your Dart models by providing a fromJson named constructor and a toJson() instance method, here's an example of one of the generated DTOs:

    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;
    }
    

    With this model you can use Dart's built-in json:convert APIs to serialize and deserialize your model to JSON, e.g:

    //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);
    

    The benefit of this approach is that it works in all Dart platforms, including Flutter and AngularDart or Dart Web Apps with and without Dart 2’s Strong Mode.

    The generated DTOs can also be used with servicestack's Dart package to enable an end to end typed solution which takes care JSON serialization into and out of your typed DTOs, e.g:

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

    For more info see docs for ServiceStack's native Dart support.

    Dart with Mirrors

    If you're using Dart in a platform where Mirrors support is available I've found using a Mixin requires the least effort, e.g:

    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;
      }  
    
    }
    

    Which you can mixin with your PODO classes with:

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

    Which you can now use with JSON.encode:

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

    Result:

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

    Note: see caveats with using Mirrors

    0 讨论(0)
  • 2020-11-28 08:34

    I have solved with:

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

    But my goal is bind data from/to json from/to model classes; This solution work if you can modify model classes, in a contrast you must use solution "external" to convert model classes;

    see also: Parsing JSON list with JsonObject library in Dart

    0 讨论(0)
提交回复
热议问题