对Flutter json_serialization中的对象进行JSON序列化和反序列化

问题描述 投票:7回答:5

由于Flutter从它的SDK中取出了dart:mirror,因此不再可能像dartson这样的库使用JSON来对象序列化/反序列化。但是我读过build_value是达到类似目的的另一种方式。我找不到任何关于如何实施它的好例子,因为它包含大量的锅炉板代码。有人能举个例子吗?例如,这是我正在尝试序列化到对象的JSON:

{
    "name":"John",
    "age":30,
    "cars": [
        { "name":"Ford", "models":[ "Fiesta", "Focus", "Mustang" ] },
        { "name":"BMW", "models":[ "320", "X3", "X5" ] },
        { "name":"Fiat", "models":[ "500", "Panda" ] }
    ]
 }
json serialization dart flutter
5个回答
9
投票

我希望从提供的答案中获得更多细节。尽管它们是很好的建议,但它们对我来说太过普遍了解。所以在做了我自己的研究之后,我将把我的实现分享给我提供的上述JSON示例,希望它可以节省别人的时间。以下是我遵循的步骤:

  • 在我的Flutter项目中,首先我导入了以下库:

依赖关系:

built_value:^ 1.0.1 built_collection:^ 1.0.0

dev依赖项:

build_runner:^ 0.3.0 built_value_generator:^ 1.0.1

  • 我创建了一个名为tool的文件夹。在其中,我放了2个文件:build.dart和watch.dart。这些文件的实现如下所示

build.dart

// Copyright (c) 2015, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

import 'dart:async';

import 'package:build_runner/build_runner.dart';
import 'package:built_value_generator/built_value_generator.dart';
import 'package:source_gen/source_gen.dart';

/// Example of how to use source_gen with [BuiltValueGenerator].
///
/// Import the generators you want and pass them to [build] as shown,
/// specifying which files in which packages you want to run against.
Future main(List<String> args) async {
  await build(
      new PhaseGroup.singleAction(
          new GeneratorBuilder([new BuiltValueGenerator()]),
          new InputSet('built_value_example', const [
            'lib/model/*.dart',
            'lib/*.dart',
          ])),
      deleteFilesByDefault: true);
}

watch.dart

// Copyright (c) 2016, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

import 'dart:async';

import 'package:build_runner/build_runner.dart';
import 'package:built_value_generator/built_value_generator.dart';
import 'package:source_gen/source_gen.dart';

/// Example of how to use source_gen with [BuiltValueGenerator].
///
/// This script runs a watcher that continuously rebuilds generated source.
///
/// Import the generators you want and pass them to [watch] as shown,
/// specifying which files in which packages you want to run against.
Future main(List<String> args) async {
  watch(
      new PhaseGroup.singleAction(
          new GeneratorBuilder([new BuiltValueGenerator()]),
          new InputSet('built_value_example', const [
            'lib/model/*.dart',
            'lib/*.dart'])),
      deleteFilesByDefault: true);
}
  • 我创建了一个serializers.dart文件,它将我的json字符串序列化为我的自定义dart对象,以及我的模型对象person.dart

serializers.dart

library serializers;

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

part 'serializers.g.dart';

Serializers serializers = (
    _$serializers.toBuilder()..addPlugin(new StandardJsonPlugin())
).build();

person.dart

library person;

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

part 'person.g.dart';

abstract class Person implements Built<Person, PersonBuilder> {
  String get name;
  int get age;
  BuiltList<Car> get cars;

  Person._();
  factory Person([updates(PersonBuilder b)]) = _$Person;
  static Serializer<Person> get serializer => _$personSerializer;
}

abstract class Car implements Built<Car, CarBuilder> {
  String get name;
  BuiltList<String> get models;

  Car._();
  factory Car([updates(CarBuilder b)]) = _$Car;
  static Serializer<Car> get serializer => _$carSerializer;
}
  • 创建上面的4个文件后,它将显示一些编译器错误。不要介意他们。这是因为build.dart文件尚未运行。因此,在此步骤中,运行build.dart。如果你正在使用Webstorm,只需右键单击build.dart并点击“Run build.dart”。这将创建2个文件:“person.g.dart”和“serializers.g.dart”。如果您仔细注意,在我们的build.dart文件中,我们将'lib / model / .dart'和'lib / .dart'放在一起。构建通过遍历指定的路径知道在哪里查找这些文件,并查找包含部分“内容”的文件。因此,在运行build.dart文件之前,将该行保留在这些文件中非常重要
  • 最后,现在我可以在main.dart文件中使用序列化程序将json字符串序列化为我的自定义dart对象类Person。在我的main.dart中,我在initState()中添加了以下代码

main.dart

  Person _person;

  @override
  void initState() {
    super.initState();
    String json = "{"
        "\"name\":\"John\",\"age\":30,\"cars\": "
        "["
        "{ \"name\":\"Ford\", \"models\":[ \"Fiesta\", \"Focus\", \"Mustang\" ] },"
        "{ \"name\":\"BMW\", \"models\":[ \"320\", \"X3\", \"X5\" ] },"
        "{ \"name\":\"Fiat\", \"models\":[ \"500\", \"Panda\" ] }"
        "]}";

    setState(() {
      _person = serializers.deserializeWith(
          Person.serializer, JSON.decode(json));
    });
  }

我的示例项目也可以在Github Built value sample project上找到


3
投票

来自Dart web site

dart:convert库提供了一个JsonCodec类,您可以使用该类自动将简单类型(map,list,int,num,string)从a转换为JSON字符串。两个关键的静态方法是JSON.encode(object)JSON.decode(string)

解码示例:

import 'dart:convert';
...    
Map<String, dynamic> parsedMap = JSON.decode(json);
print(parsedMap['name']); // John
print(parsedMap['age']); // 30

编码示例:

Map<String, dynamic> mapData = <String, dynamic>{ 'hello': 'world!' };
String jsonData = JSON.encode(mapData); // convert map to String

如果你想让你的JSON膨胀成自定义Dart类而不是原始对象树,Hadrien的答案应该指向正确的方向,但我只是想把它留在这里以防其他人试图获得基本的JSON序列化/反序列化工作。


2
投票

您可以使用Jaguar Serializer,它很容易启动并完美地用于Flutter或Server和Web dev。

https://github.com/Jaguar-dart/jaguar_serializer


1
投票

您应该为Built_value准备一个配置文件,它将解析您的dart源并生成.g.dart。一旦准备好json序列化是自动的。您可以生成这些文件一次或使用watch命令。

这些文件将添加到与source和dart命令相同的级别

part of data;

被视为同一类。

这是我在Flutter项目中使用的配置:

import 'dart:async';

import 'package:build_runner/build_runner.dart';
import 'package:built_value_generator/built_value_generator.dart';
import 'package:source_gen/source_gen.dart';


Future main(List<String> args) async {

await build(

new PhaseGroup.singleAction(

new GeneratorBuilder([

new BuiltValueGenerator(),

]),

new InputSet('flutter_project', const ['lib/data/*.dart'])),

deleteFilesByDefault: true);

}

您可能会发现David Morgan阅读所有帖子以了解其中的好处。需要一些时间来改变你的想法,但这是一个非常好的模式。

https://medium.com/dartlang/darts-built-value-for-immutable-object-models-83e2497922d4

https://medium.com/dartlang/darts-built-value-for-serialization-f5db9d0f4159

诀窍是了解sourcegen如何解析,然后通过添加许多行为(如Builders和Serializers)来丰富您的类。


1
投票

json_serialization

Dart Team的This package在一个单独的文件中生成fromJson构造函数和toJson方法所需的所有内容。

Dependencies

添加以下依赖项:

dependencies:
  json_annotation: ^2.0.0

dev_dependencies:
  build_runner: ^1.0.0
  json_serializable: ^2.0.0

Model class

调整您的模型类以包含以下部分:

import 'package:json_annotation/json_annotation.dart';

// will be generated later
part 'person.g.dart';

@JsonSerializable()
class Person {
  Person(this.name, this.age);

  final String name;
  final int age;

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

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

Generate code

从终端生成person.g.dart文件:

flutter packages pub run build_runner build

Use it

然后像这样使用它:

JSON→对象

String rawJson = '{"name":"Mary","age":30}';
Map<String, dynamic> map = jsonDecode(rawJson);
Person person = Person.fromJson(map);

对象→JSON

Person person = Person('Mary', 30);
Map<String, dynamic> map = person.toJson();
String rawJson = jsonEncode(map);

Notes

  • 在Dart项目中使用pub run build_runner build
  • 有关序列化JSON的更多方法,请参阅this answer
© www.soinside.com 2019 - 2024. All rights reserved.