Flutter json 序列化与反序列化
在开发 Flutter 仿网易云音乐的过程中,需要与后端交互。由于后端返回的是 json 格式,那么我们需要把 json 格式的返回值转换为 Dart 的强类型对象。查阅了一下 Flutter 的开发文档,有以下几种方式:
- 手动写Model序列化数据(一般试用于小项目)
- dart:convert
- 利用代码生成Model序列化数据
- json_serializable
- built_value。
后面所有的例子都以这个 json 为原始数据,名称为 jsonData
{
"age":10,
"first_name":"yang",
"secondName": "yun",
"listInt": [1, 2, 3],
"listString": ["a", "b", "c"]
}
dart:convert
- 声明一个 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(),
);
}
}
- 使用
import 'dart:convert';
var person = Person.fromJson(json.decode(jsonResponse) as Map<String, dynamic>);
json_serializable
- 导入依赖
dependencies:
json_annotation: ^2.2.0
dev_dependencies:
build_runner: ^1.0.0
json_serializable: ^2.2.0
- 按照格式写 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);
}
- 执行 flutter pub run build_runner build
- 使用生成的类
import 'dart:convert';
import 'person.dart';
var person = Person.fromJson(json.decode(jsonResponse) as Map<String, dynamic>);
关于 json_serializable 的许多特殊的注解可以参考
- @JsonKey 对于字段的注解;使用方式参考:这里
- @JsonSerializable 对于类的注解;使用方式参考:这里
- @JsonLiteral 可以从本地的 json 文件中生成类或者属性;使用方式参考:这里
但是这个库每次都要重复写不少的代码,在这个库的基础上,开发了一个基于 json 生成类的库,然后在使用 json_serializable 生成 json 的转换代码。可以参考 json_to_dart_model.
built_value
- 引入依赖
dev_dependencies:
build_runner: ^1.0.0
built_value_generator: '6.3.0'
- 按照格式写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();
- 执行 flutter pub run build_runner build
会生成 person.g.dart 和 serializers.g.dart
- 使用生成的类
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 的。