flutter 反序列化
一、内联反序列化
把JSON字符串转换成 Map<String, dynamic> 或者 List<dynamic>
import 'dart:convert'; main(List<String> args) { JsonCodec json = new JsonCodec(); String str = '{"name":"tom"}'; Map<String, dynamic> a = json.decode(str); print(a["name"]); String str1 = '["a","b"]'; List<dynamic> b = json.decode(str1); print(b.length); String str3 = '{"name": "John Smith","email": "john@example.com"}'; var c = json.decode(str3); print(c.runtimeType); //Map<String, dynamic> String str4 = '{"name": "John Smith","email": ["a","b"]}'; var d = json.decode(str4); print(d.runtimeType); //Map<String, dynamic> String str5 = '{"name": "John Smith","email": {"a":"o","b":"p"}}'; var e = json.decode(str5); print(e.runtimeType); //<String, dynamic> // String str6 = '{"name": "John Smith","email": {"a","b"}}'; // var f = json.decode(str6); //FormatException: Unexpected character 报错 // print(e.runtimeType); }
复杂些的比如
二、把字符串转成类对象
import 'dart:convert'; main(List<String> args) { String str = '{"age":19,"name":"tom"}'; Map map = jsonDecode(str); Student user = Student.ds(map); print(user.age); } class Student { int age; String name; //Student(this.age, this.name); Student.ds(Map<String, dynamic> json) : age = json['age'], name = json['name']; }
三、自动反序列化
使用 json_serializable https://pub.dev/packages/json_serializable
说明:用指令生成文件是在flutter中进行的,实际测试是在vscode中执行的。
不知道为什么flutter下使用flutter pub run build_runner build 正常,但是vscode中使用dart里的指令pub run build_runner build 生成不了文件。还有各式各样的版本问题,折腾了很久,感觉还不成熟
测试版本
Flutter 1.20.4 • channel stable
Dart SDK version: 2.9.2
导入包的版本
dependencies: flutter: sdk: flutter json_annotation: ^3.0.0 dev_dependencies: flutter_test: sdk: flutter build_runner: ^1.6.7 json_serializable: ^3.2.2
user.dart
import 'package:json_annotation/json_annotation.dart'; part 'user.g.dart'; @JsonSerializable() class User { User(this.name, this.email); String name; String email; factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); Map<String, dynamic> toJson() => _$UserToJson(this); }
*.g.dart里 *要跟文件名相同
在flutter项目的根目录下,也就是有pubspec.yaml文件夹下,使用指令:flutter pub run build_runner build
如果想要自动序列化使用指令:flutter pub run build_runner watch
生成后的文件 user.g.dart
// GENERATED CODE - DO NOT MODIFY BY HAND part of 'user.dart'; // ************************************************************************** // JsonSerializableGenerator // ************************************************************************** User _$UserFromJson(Map<String, dynamic> json) { return User( json['name'] as String, json['email'] as String, ); } Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{ 'name': instance.name, 'email': instance.email, };
使用
import 'dart:convert'; import './user.dart'; main(List<String> args) { String jsonString = '{"name": "John", "email": "abc@163.com"}'; //序列化成map Map<String, dynamic> map = jsonDecode(jsonString); //转成对象 User user = User.fromJson(map); print(user.email); //json print(user.toJson()); }
反序列化嵌套json
结构
user.dart
import 'address.dart'; import 'package:json_annotation/json_annotation.dart'; part 'user.g.dart'; @JsonSerializable() class User { String firstName; Address address; User(this.firstName, this.address); factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); Map<String, dynamic> toJson() => _$UserToJson(this); }
address.dart
import 'package:json_annotation/json_annotation.dart'; part 'address.g.dart'; @JsonSerializable() class Address { String street; String city; Address(this.street, this.city); factory Address.fromJson(Map<String, dynamic> json) => _$AddressFromJson(json); Map<String, dynamic> toJson() => _$AddressToJson(this); }
生成后的代码
user.g.dart
// GENERATED CODE - DO NOT MODIFY BY HAND part of 'user.dart'; // ************************************************************************** // JsonSerializableGenerator // ************************************************************************** User _$UserFromJson(Map<String, dynamic> json) { return User( json['firstName'] as String, json['address'] == null ? null : Address.fromJson(json['address'] as Map<String, dynamic>), ); } Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{ 'firstName': instance.firstName, 'address': instance.address, };
这里有个问题,不知道为什么生成的这个user.g.dart文件在as中不报错,但是在vscode中报错
稍微改了一下,改成
return User( json['firstName'] as String, json['address'] = Address.fromJson(json['address'] as Map<String, dynamic>), );
address.g.dart
// GENERATED CODE - DO NOT MODIFY BY HAND part of 'address.dart'; // ************************************************************************** // JsonSerializableGenerator // ************************************************************************** Address _$AddressFromJson(Map<String, dynamic> json) { return Address( json['street'] as String, json['city'] as String, ); } Map<String, dynamic> _$AddressToJson(Address instance) => <String, dynamic>{ 'street': instance.street, 'city': instance.city, };
测试运行
import 'dart:convert'; import './user.dart'; main(List<String> args) { String jsonString = '{"firstName": "John", "address": {"street":"女贞路45号","city":"霍格沃茨"}}'; //序列化成map Map<String, dynamic> map = jsonDecode(jsonString); //转成对象 User user = User.fromJson(map); print(user.firstName); // print(user.address.city); //json print(user.toJson()); }
对象都成功输出了
但是嵌套类转JSON的这个结果不是想要的.
修改user.dart
//括号里添加 @JsonSerializable(explicitToJson: true) class User { String firstName; Address address;
修改user.g.dart
User _$UserFromJson(Map<String, dynamic> json) { return User( json['firstName'] as String, //上面已经修改过 json['address'] = Address.fromJson(json['address'] as Map<String, dynamic>), ); }
这个转json问题flutter里能成功,在vscode里纯dart方式失败?
修改user.g.dart 不是个好方法,使用指令时肯定有重新变回去了。