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

roqulrg3  于 2023-01-06  发布在  Flutter
关注(0)|答案(6)|浏览(257)

自从Flutter干掉了Dart之后:的SDK镜像,所以不再可能使用像dartson for 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" ] }
    ]
 }
63lcw9qa

63lcw9qa1#

我希望从提供的答案中获得更多细节。尽管它们是很好的建议,但它们太笼统了,我无法理解。因此,在做了自己的研究之后,我将分享我对上面JSON示例的实现,希望它能节省其他人的时间。因此,以下是我遵循的步骤:

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

依赖性:
构建值:^1.0.1
构建集合:^1.0.0
设备依赖项:
生成运行程序:^0.3.0
内部值生成器:^1.0.1

  • 我创建了一个名为工具的文件夹。在其中,我放了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并点击"运行build.dart"。这将创建2个文件:"person. g. dart"和"serializers. g. dart"。如果您仔细注意,在我们的build.dart文件中,我们放置了"lib/model/. dart"和"lib/. dart"。通过遍历指定的路径,构建知道在哪里查找这些文件,并查找包含"something"部分的文件。因此,在运行build.dart文件之前,在这些文件中保留该行非常重要
  • 最后,现在我可以使用main.dart文件中的序列化器将json字符串序列化为我的自定义dart对象类Person。

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上找到

f5emj3cl

f5emj3cl2#

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

依赖项

添加以下依赖项:

dependencies:
  json_annotation: ^2.0.0

dev_dependencies:
  build_runner: ^1.0.0
  json_serializable: ^2.0.0

型号类别

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

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);
}

生成代码

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

flutter packages pub run build_runner build

∮用它∮
然后像这样使用它:

    • 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);

注解

  • 在Dart项目中,使用pub run build_runner build
  • 有关序列化JSON的更多方法,请参见this answer
9cbw7uwe

9cbw7uwe3#

从Dart网站:
convert库提供了一个JsonCodec类,你可以使用它自动地将简单类型(map、list、int、num、string)从和转换为JSON字符串。
解码示例:

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序列化/反序列化。

jv4diomz

jv4diomz4#

您可以使用Jaguar Serializer,它很容易启动,并完美地为Flutter或服务器和Web开发工作。
https://github.com/Jaguar-dart/jaguar_serializer

kg7wmglp

kg7wmglp5#

您应该为Built_value准备一个配置文件,该文件将解析您的dart源代码并生成. g.dart。一旦准备就绪,json序列化将自动进行。您可以一次性生成这些文件,也可以使用监视命令。
这些文件将添加到与源和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);

}

你可能会发现阅读大卫·摩根的所有帖子来了解它的好处是很有用的。这需要一些时间来改变你的想法,但这是一个非常好的模式。
https://medium.com/dartlang/darts-built-value-for-immutable-object-models-83e2497922d4
https://medium.com/dartlang/darts-built-value-for-serialization-f5db9d0f4159
诀窍在于理解sourcegen如何解析类,然后通过添加大量行为(如构建器和序列化器)来丰富类。

noj0wjuj

noj0wjuj6#

1) first put json code to any convert website ex: 
            [JSON to Darthttps://javiercbk.github.io ›][1] 
            it will give like this output 
            
            
                class Autogenerated {
                  int? code;
                  List<Result>? result;
                  String? status;
                
                  Autogenerated({this.code, this.result, this.status});
                
                  Autogenerated.fromJson(Map<String, dynamic> json) {
                    code = json['code'];
                    if (json['result'] != null) {
                      result = <Result>[];
                      json['result'].forEach((v) {
                        result!.add(new Result.fromJson(v));
                      });
                    }
                    status = json['status'];
                  }
                
                  Map<String, dynamic> toJson() {
                    final Map<String, dynamic> data = new Map<String, dynamic>();
                    data['code'] = this.code;
                    if (this.result != null) {
                      data['result'] = this.result!.map((v) => v.toJson()).toList();
                    }
                    data['status'] = this.status;
                    return data;
                  }
                }
                
                class Result {
                  int? id;
                  int? projectId;
                  String? projectName;
                  int? userId;
                  String? userName;
                
                  Result(
                      {this.id, this.projectId, this.projectName, this.userId, this.userName});
                
                  Result.fromJson(Map<String, dynamic> json) {
                    id = json['id'];
                    projectId = json['project_id'];
                    projectName = json['project_name'];
                    userId = json['user_id'];
                    userName = json['user_name'];
                  }
                
                  Map<String, dynamic> toJson() {
                    final Map<String, dynamic> data = new Map<String, dynamic>();
                    data['id'] = this.id;
                    data['project_id'] = this.projectId;
                    data['project_name'] = this.projectName;
                    data['user_id'] = this.userId;
                    data['user_name'] = this.userName;
                    return data;
                  }
                }
        
        --------------------------------------------------------------------------------------
and change that code like  this format for easy use 
                
                ***get_client.dart***   
                
                 import 'package:json_annotation/json_annotation.dart';
                    
                    part 'get_client.g.dart';
                    
                    @JsonSerializable(
                      explicitToJson: true,
                    )
                    class ClientModel {
                      @JsonKey(name: "address1")
                      String? address1;
                      @JsonKey(name: "city")
                      int? city;
                      @JsonKey(name: "city_name")
                      String? cityName;
                      @JsonKey(name: "country")
                      int? country;
                      @JsonKey(name: "country_name")
                      String? countryName;
                      @JsonKey(name: "email")
                      String? email;
                      @JsonKey(name: "first_name")
                      String? firstName;
                      @JsonKey(name: "gender")
                      String? gender;
                      @JsonKey(name: "id")
                      int? id;
                      @JsonKey(name: "last_name")
                      String? lastName;
                      @JsonKey(name: "mobile_no")
                      String? mobileNo;
                      @JsonKey(name: "password")
                      String? password;
                      @JsonKey(name: "pincode")
                      String? pincode;
                      @JsonKey(name: "role")
                      int? role;
                      @JsonKey(name: "role_name")
                      String? roleName;
                      @JsonKey(name: "state")
                      int? state;
                      @JsonKey(name: "state_name")
                      String? stateName;
                    
                      ClientModel(
                          {this.address1,
                          this.city,
                          this.cityName,
                          this.country,
                          this.countryName,
                          this.email,
                          this.firstName,
                          this.gender,
                          this.id,
                          this.lastName,
                          this.mobileNo,
                          this.password,
                          this.pincode,
                          this.role,
                          this.roleName,
                          this.state,
                          this.stateName});
                    
                      factory ClientModel.fromJson(Map<String, dynamic> map) =>
                          _$ClientModelFromJson(map);
                    
                      Map<String, dynamic> toJson() => _$ClientModelToJson(this);
                    }
            
            -------------------------------------------------------------------
            
            
              [1]: https://%20JSON%20to%20Darthttps://javiercbk.github.io%20%E2%80%BA
        
        after run build runner cmd in terminal 
        ***flutter pub run build_runner build*** 
        
        then it will create the following output file 
        // GENERATED CODE - DO NOT MODIFY BY HAND
        
        part of 'get_client.dart';
        
        // **************************************************************************
        // JsonSerializableGenerator
        // **************************************************************************
        
        ClientModel _$ClientModelFromJson(Map<String, dynamic> json) => ClientModel(
              address1: json['address1'] as String?,
              city: json['city'] as int?,
              cityName: json['city_name'] as String?,
              country: json['country'] as int?,
              countryName: json['country_name'] as String?,
              email: json['email'] as String?,
              firstName: json['first_name'] as String?,
              gender: json['gender'] as String?,
              id: json['id'] as int?,
              lastName: json['last_name'] as String?,
              mobileNo: json['mobile_no'] as String?,
              password: json['password'] as String?,
              pincode: json['pincode'] as String?,
              role: json['role'] as int?,
              roleName: json['role_name'] as String?,
              state: json['state'] as int?,
              stateName: json['state_name'] as String?,
            );
        
        Map<String, dynamic> _$ClientModelToJson(ClientModel instance) =>
            <String, dynamic>{
              'address1': instance.address1,
              'city': instance.city,
              'city_name': instance.cityName,
              'country': instance.country,
              'country_name': instance.countryName,
              'email': instance.email,
              'first_name': instance.firstName,
              'gender': instance.gender,
              'id': instance.id,
              'last_name': instance.lastName,
              'mobile_no': instance.mobileNo,
              'password': instance.password,
              'pincode': instance.pincode,
              'role': instance.role,
              'role_name': instance.roleName,
              'state': instance.state,
              'state_name': instance.stateName,
            };
    
    
    
    after we can use like this in repository file 
    
    static Future<dynamic> getAllClients(int id) async {
        String url = "${HttpUrls.clientList}/${0}";
        Response response = await dio.get(url);
        if (response.statusCode == 200) {
          List<ClientModel> clientLists = (response.data['result'] as List)
              .map((eachItem) => ClientModel.fromJson(eachItem))
              .toList();
          print(clientLists.toString());
          if (clientLists.isNotEmpty) {
            return clientLists;
          }
        } else {
          BaseResponse baseResponse =
              BaseResponse.fromJson(response.data as Map<String, dynamic>);
          return baseResponse;
        }
      }

相关问题