Dart 处理json,built_value库

原文链接

文档

import 'dart:convert';

main() async {
  // json 转化为 map
  String jsonStr = '''
    [
      {"name": "ajanuw"},
      {"name": "suou"}
    ]
  ''';

  var jsonObj = jsonDecode(jsonStr);
  print(jsonObj[0]['name'] == 'ajanuw'); // true

  // list<Map> 转化为 json字符串
  var scores = [
    {'score': 40},
    {'score': 80},
    {'score': 100, 'overtime': true, 'special_guest': null}
  ];
  var jsonText = jsonEncode(scores);
  print(jsonText);
}

JSON to Dart

import 'dart:convert';

class MyInfo {
  MyInfo({this.age, this.name});

  String name;
  int age;

  factory MyInfo.fromJson(Map<String, dynamic> jsonMap) {
    return MyInfo(
      name: jsonMap['name'],
      age: jsonMap['age'],
    );
  }
}

main(List<String> args) {
  String jsonStr = '''
    {
      "name": "ajanuw",
      "age": 12
    }
  ''';
  var parsed = jsonDecode(jsonStr);
  MyInfo data = MyInfo.fromJson(parsed);
  print(data.age);
}

使用“built_value”库来处理json

我在这里使用"stagehand console-full"创建的项目示例,项目名叫"dart_test"

1) 安装依赖

dependencies:
  ...
  built_value:
  built_collection:

dev_dependencies:
  ...
  build_runner:
  built_value_generator:
  1. 准备json数据
{
      "id": 157538,
      "date": "2017-07-21T10:30:34",
      "date_gmt": "2017-07-21T17:30:34",
      "type": "post",
      "link": "https://example.com",
      "title": {
          "rendered": "Json 2 dart built_value converter"
      },
      "tags": [
          1798,
          6298
      ]
}
  1. 创建文件"lib/models/hello.dart",文件名很重要必须要要和你的class名一样
import 'dart:convert';

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

part 'hello.g.dart';

abstract class Hello implements Built<Hello, HelloBuilder> {
  Hello._();

  factory Hello([updates(HelloBuilder b)]) = _$Hello;

  @BuiltValueField(wireName: 'id')
  int get id;
  @BuiltValueField(wireName: 'date')
  String get date;
  @BuiltValueField(wireName: 'date_gmt')
  String get dateGmt;
  @BuiltValueField(wireName: 'type')
  String get type;
  @BuiltValueField(wireName: 'link')
  String get link;
  @BuiltValueField(wireName: 'title')
  Title get title;

  @nullable // 可为空,返回null
  @BuiltValueField(wireName: 'tags')
  BuiltList<int> get tags;

  String toJson() {
    return jsonEncode(serializers.serializeWith(Hello.serializer, this));
  }

  static Hello fromJson(String jsonString) {
    return serializers.deserializeWith(
        Hello.serializer, jsonDecode(jsonString));
  }

  static Serializer<Hello> get serializer => _$helloSerializer;
}

abstract class Title implements Built<Title, TitleBuilder> {
  Title._();

  factory Title([updates(TitleBuilder b)]) = _$Title;

  @BuiltValueField(wireName: 'rendered')
  String get rendered;

  String toJson() {
    return jsonEncode(serializers.serializeWith(Title.serializer, this));
  }

  static Title fromJson(String jsonString) {
    return serializers.deserializeWith(
        Title.serializer, jsonDecode(jsonString));
  }

  static Serializer<Title> get serializer => _$titleSerializer;
}
  1. 保存文件后,在项目根目录下运行命令, 生成"lib/models/hello.g.dart"文件
flutter packages pub run build_runner build   // 执行一次build命令
flutter packages pub run build_runner watch  // 文件更改自动build
flutter packages pub run build_runner watch --delete-conflicting-outputs  // 删除旧文件在build
  1. 创建"lib/models/serializers.dart"文件,编写下面的代码后,保存会生成"lib/models/serializers.g.dart"文件
import 'package:built_collection/built_collection.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
import 'package:dart_test/models/hello.dart';

part 'serializers.g.dart';

@SerializersFor(const [
  Hello
])
final Serializers serializers = (_$serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
  1. 编写“bin/main.dart"
import 'package:dart_test/models/hello.dart';

String jsonStr = '''
 {
      "id": 157538,
      "date": "2017-07-21T10:30:34",
      "date_gmt": "2017-07-21T17:30:34",
      "type": "post",
      "link": "https://example.com",
      "title": {
          "rendered": "Json 2 dart built_value converter"
      },
      "tags": [
          1798,
          6298
      ]
    }
''';

main(List<String> args) {
  Hello hello = Hello.fromJson(jsonStr);
  print(hello.title.rendered);
  print(hello.tags.length);
}
  1. 保存文件后执行
> dart bin/main.dart
Json 2 dart built_value converter
2

在vscode中隐藏 “*.g.dart”生成的文件

  "files.exclude": {
    "**/*.g.dart": true
  }

built_value处理json不要有这样的数据 { key: [[{}], [{}],...] } 转换为这样: { key: [{key: []}, {key: []},...] }

创建枚举

  int get age;
  TypeStatus get type => age < 10 ? TypeStatus.a : TypeStatus.b;

enum TypeStatus {
  a,
  b,
}
 // or
class TypeStatus extends EnumClass {
  static const TypeStatus a = _$a;
  static const TypeStatus b = _$b;
  const TypeStatus._(String name) : super(name);
  static BuiltSet<TypeStatus> get values => _$values;
  static TypeStatus valueOf(String name) => _$valueOf(name);
}

手动创建dto模型

import 'dto/hello_dto/hello_dto.dart';

String jsonStr = '''
 {
      "id": 157538,
      "date": "2017-07-21T10:30:34",
      "date_gmt": "2017-07-21T17:30:34",
      "type": "post",
      "link": "https://example.com",
      "title": {
          "rendered": "Json 2 dart built_value converter"
      },
      "tags": [
          1798,
          6298
      ]
    }
''';

main(List<String> args) {
  var r = HelloDto(
    (b) => b
      ..id = 1
      ..date = 'date'
      ..dateGmt = 'dateGmt'
      ..type = 'get'
      ..link = 'link'
      ..title.rendered = 'title'
      ..tags.addAll([1, 2]),
  );

  print(r);
}
λ dart test.dart
HelloDto {
  id=1.0,
  date=date,
  dateGmt=dateGmt,
  type=get,
  link=link,
  title=TitleDto {
    rendered=title,
  },
  tags=[1, 2],
  arrobj=[],
}

rebuild重建实例

  var hello = HelloDto.fromJson(jsonStr);
  var hello2 = hello.rebuild((b) => b.type = 'get');
  print(hello == hello2); // false
   
  // 数据一样是相等的
  var hello = HelloDto.fromJson(jsonStr);
  var hello2 = HelloDto.fromJson(jsonStr);
  print(hello == hello2); // true

在flutter中更新数据

import 'package:flutter/material.dart';
import 'package:flutter_demo/dto/hello_dto/hello_dto.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  List<HelloDto> data;

  @override
  void initState() {
    super.initState();

    data = HelloDto.fromListJson('''[{"a":"a1","b":"b1"},{"a":"a2","b":"b2"}]''');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Page'),
      ),
      body: ListView(
        children: <Widget>[
          for (var it in data)
            ListTile(
              title: Text(it.a),
              subtitle: Text(it.b),
            ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            data[0] = data[0].rebuild((b) => b.a = 'new title');
          });
        },
        child: Icon(Icons.hot_tub),
      ),
    );
  }
}

为可能为null的数据设置默认值

  @nullable
  @BuiltValueField()
  int get id;

  static HelloDto fromJson(String jsonString) {
    return serializers
        .deserializeWith(HelloDto.serializer, jsonDecode(jsonString))
        .rebuild(
           // 在这里设置
          (b) => b..id ??= 0,
        );
  }
  var hello = HelloDto.fromJson('{"id": null}');
  print(hello);
  print(hello.id); //=> 0