Flutter json 序列化与反序列化

4,353 阅读2分钟

Flutter json 序列化与反序列化

在开发 Flutter 仿网易云音乐的过程中,需要与后端交互。由于后端返回的是 json 格式,那么我们需要把 json 格式的返回值转换为 Dart 的强类型对象。查阅了一下 Flutter 的开发文档,有以下几种方式:

  1. 手动写Model序列化数据(一般试用于小项目)
  • dart:convert
  1. 利用代码生成Model序列化数据
  • json_serializable
  • built_value。

后面所有的例子都以这个 json 为原始数据,名称为 jsonData

{
  "age":10,
  "first_name":"yang",
  "secondName": "yun",
  "listInt": [1, 2, 3],
  "listString": ["a", "b", "c"]
}

dart:convert

  1. 声明一个 Class 用于转换。
class Person {
  final int age;
  final String firstName;
  final String secondName;
  final List<int> listInt;
  final List<String> listStr;

  const Person({
    this.age,
    this.firstName,
    this.secondName,
    this.listInt,
    this.listStr,
  });

  factory Person.fromJson(Map<String, dynamic> json) {
    if (json == null) return null;
    return Person(
      age: json["age"] as int,
      firstName: json["first_name"] as String,
      secondName: json["secondName"] as String,
      listInt: (json['listInt'] as List)?.map((e) => e as int)?.toList(),
      listStr: (json['listString'] as List)?.map((e) => e as String)?.toList(),
    );
  }
}
  1. 使用
import 'dart:convert';
 
var person = Person.fromJson(json.decode(jsonResponse) as Map<String, dynamic>);

json_serializable

  1. 导入依赖
dependencies:
  json_annotation: ^2.2.0

dev_dependencies:
  build_runner: ^1.0.0
  json_serializable: ^2.2.0
  1. 按照格式写 Model 类
import 'package:json_annotation/json_annotation.dart';

part 'person.g.dart';

@JsonSerializable()
class Person  {
  Person({
    this.age,this.firstName,this.secondName,this.listInt,this.listStr
  });

  final int age;

  @JsonKey(name: 'first_name', nullable: false)
  final String firstName;

  final String secondName;

  final List <int> listInt;

  final List <String> listStr;


  factory Person.fromJson(Map<String,dynamic> json) => _$PersonFromJson(json);

  Map<String, dynamic> toJson() => _$PersonToJson(this);
}
  1. 执行 flutter pub run build_runner build
  2. 使用生成的类
import 'dart:convert';
import 'person.dart';

var person = Person.fromJson(json.decode(jsonResponse) as Map<String, dynamic>);

关于 json_serializable 的许多特殊的注解可以参考

  1. @JsonKey 对于字段的注解;使用方式参考:这里
  2. @JsonSerializable 对于类的注解;使用方式参考:这里
  3. @JsonLiteral 可以从本地的 json 文件中生成类或者属性;使用方式参考:这里

但是这个库每次都要重复写不少的代码,在这个库的基础上,开发了一个基于 json 生成类的库,然后在使用 json_serializable 生成 json 的转换代码。可以参考 json_to_dart_model.

built_value

  1. 引入依赖
dev_dependencies:
  build_runner: ^1.0.0
  built_value_generator: '6.3.0'
  1. 按照格式写Model类

person.dart

import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:built_collection/built_collection.dart';

part 'person.g.dart';

abstract class Person implements Built<Person, PersonBuilder> {
  static Serializer<Person> get serializer => _$personSerializer;

  // can't be null
  int get age;

  @nullable
  @BuiltValueField(wireName: 'first_name')
  String get firstName;

  @nullable
  String get secondName;

  @nullable
  BuiltList<int> get listInt;

  @nullable
  @BuiltValueField(wireName: 'listString')
  BuiltList<String> get listStr;

  Person._();
  factory Person([void Function(PersonBuilder) updates]) = _$Person;
}

serializers.dart

import 'package:built_collection/built_collection.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
import 'person.dart';

part 'serializers.g.dart';

@SerializersFor(const [
  Person,
])

final Serializers serializers =
    (_$serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
  1. 执行 flutter pub run build_runner build

会生成 person.g.dart 和 serializers.g.dart

  1. 使用生成的类
import 'dart:convert';
import 'package:flutter_music_163/model/person.dart';
import 'package:flutter_music_163/model/serializers.dart';

void main() {
  var person = serializers.deserializeWith(Person.serializer, json.decode(jsonResponse)); // Person.fromJson(json.decode(jsonResponse) as Map<String, dynamic>);
  print("${person.firstName} ${person.secondName}'s age is ${person.age}; ${person.listInt}; ${person.listStr}");
}

在使用 built_value 的过程中,如果直接使用 7.0.0 的版本安装时会报错,我使用的版本是 6.3.0 的。