Flutter如何高效的JSON转Model

背景

因为Flutter禁用运行时反射,因此在Flutter中是没有GSONJackson这类解析JSON的库。官方解释运行时反射会干扰Dart_tree shaking_。使用_tree shaking_咱们能够在发版时去除未使用的代码。这能够显着优化应用程序的大小。 因为反射会默认使用全部代码,所以_tree shaking_会很难工做。这些工具没法知道哪些widget在运行时未被使用,所以冗余代码很难剥离。使用反射时,应用尺寸没法轻松的进行优化。html

手动序列化JSON

使用Flutter内置的dart:convert库作基本的JSON序列化很简单:git

Map<String, dynamic> person = JSON.decode(json);
print('${person['name']}');
print('${person['age']');
复制代码

JSON.decode()返回一个Map<String, dynamic>,这意味着咱们直到运行时才知道值的类型。这种方法,咱们失去了静态类型语言特性,代码很是容易出错。不推荐。github

固然咱们也能够手动在模型类中序列化JSONjson

class Person {
  final String name;
  final String age;

  User(this.name, this.age);

  User.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        age = json['age'];

  Map<String, dynamic> toJson() =>
    {
      'name': name,
      'age': age,
    };
}
复制代码
Map personMap = JSON.decode(json);
var person = new Person.fromJson(personMap);
print('${person.name}');
print('${person.age}');
复制代码

这样咱们调用代码能够具备类型安全、自动补全字段以及编译时异常等静态类型语言特性。若是拼写或者类型错误就不会经过编译,而不是在运行时崩溃。安全

在项目实战中JSON对象不多会这么简单,各类ListMap嵌套的JSON也是很常见的。如何安全且高效的JSONModel才是咱们想要的。bash

使用 json_serializable

json_serializable是一个自动化的源代码生成器,能够为咱们生成JSON序列化模板。在pubspec.yaml中添加依赖并执行flutter pub getmarkdown

dependencies:
  json_annotation: ^3.0.0

dev_dependencies:
  build_runner: ^1.0.0
  json_serializable: 3.2.0
复制代码

这里没有使用最新版本由于咱们Flutter版本为v1.9.1+hotfix.6Dart版本比较低。app

  1. 生成模型类

生成模型类咱们使用一位大佬写的json2dart工具。工具

假设mock了一个JSONoop

[
    {
      "name": "小龙女",
      "age": "18",
      "tele": "13888888888"
    },
    {
      "name": "杨过",
      "age": "18",
      "tele": "13666666666"
    },
    {
      "name": "尹志平",
      "age": "18",
      "tele": "13333333333"
    }
]
复制代码

工具使用很简单直接粘贴生成对应的类名称

此时咱们将生成的代码 copy出来粘在咱们建立的模型类中。

import 'package:json_annotation/json_annotation.dart'; 
  
part 'person_model.g.dart';

List<PersonModel> getPersonModelList(List<dynamic> list){
    List<PersonModel> result = [];
    list.forEach((item){
      result.add(PersonModel.fromJson(item));
    });
    return result;
  }
@JsonSerializable()
  class PersonModel extends Object {

  @JsonKey(name: 'name')
  String name;

  @JsonKey(name: 'age')
  String age;

  @JsonKey(name: 'tele')
  String tele;

  PersonModel(this.name,this.age,this.tele,);

  factory PersonModel.fromJson(Map<String, dynamic> srcJson) => _$PersonModelFromJson(srcJson);

  Map<String, dynamic> toJson() => _$PersonModelToJson(this);

}
复制代码

这里须要注意这个工具可能有少字段的状况,若是是ListJSON只会取其中的第一个(小龙女)来生成模型的字段。也就是若是后面的Item(杨过,尹志平)字段数量大于第一个也会按照第一个的字段来生成。

  1. 运行代码生成程序

上面的模型类生成以后会先报错,由于模型类的生成代码还不存在,因此咱们须要运行代码生成器来为咱们生成序列化模板。

  • 一次性生成flutter packages pub run build_runner build
  • 持续生成flutter packages pub run build_runner watch

这里选择哪一种方式取决于你的改动频率,推荐使用watch的方式。

  1. 使用
Map personList = JSON.decode(json);
var list = getPersonModelList(personList);
复制代码

json_serializable这种方式,咱们能够轻松的生成一个模型类。经过源代码生成器建立一个g.dart的文件,它具备全部必需的序列化逻辑。

使用工具网站

app.quicktype.io是一个将JSON转换成模型类的工具网站,目前来看支持大部分经常使用语言,而且灵活的可选项也很是多:

这里咱们仍是用上面的JSON作一下尝试:

生成的模型类是使用了Flutter内置的dart:convert作序列化。

// To parse this JSON data, do
//
//     final personModel = personModelFromJson(jsonString);

import 'dart:convert';

List<PersonModel> personModelFromJson(String str) => List<PersonModel>.from(json.decode(str).map((x) => PersonModel.fromJson(x)));

String personModelToJson(List<PersonModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class PersonModel {
    String name;
    String age;
    String tele;

    PersonModel({
        this.name,
        this.age,
        this.tele,
    });

    factory PersonModel.fromJson(Map<String, dynamic> json) => PersonModel(
        name: json["name"],
        age: json["age"],
        tele: json["tele"],
    );

    Map<String, dynamic> toJson() => {
        "name": name,
        "age": age,
        "tele": tele,
    };
}
复制代码

能够看到这个模型类正是咱们须要的,使用方式也在上面注释的很清楚,目前来说这种方式操做起来会比使用json_serializable操做起来更简便一些。

总结

  • 手动序列化JSON:比较麻烦,效率低,但新手仍是多作尝试和了解比较好。
  • json_serializable:效率高,watch很好用。
  • 工具网站:效率高,更多功能可选。

整体推荐使用后两种,能够大大提高开发效率,不用埋头去搞一些重复的序列化工做。

相关文章
相关标签/搜索