JSON serialization and deserialization of objects in Flutter

Since Flutter pulled dart: mirror from its SDK, libraries such as dartson for JSON can no longer be used for object serialization / deserialization. However, I read that build_value is another way to achieve a similar goal. I could not find good examples of how to implement this, since it contains a significant amount of boiler plate code. Can someone give an example? For example, this is JSON, which I am trying to serialize into objects:

{
    "name":"John",
    "age":30,
    "cars": [
        { "name":"Ford", "models":[ "Fiesta", "Focus", "Mustang" ] },
        { "name":"BMW", "models":[ "320", "X3", "X5" ] },
        { "name":"Fiat", "models":[ "500", "Panda" ] }
    ]
 }
+7
source share
6 answers

. , , , . , , JSON, , - . , , :

  • Flutter :

:

built_value: ^ 1.0.1
built_collection: ^ 1.0.0

dev_dependencies:

build_runner: ^ 0.3.0
built_value_generator: ^ 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 model 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. , , , "-". build.dart

  • , main.dart, json dart. 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

+9

- Dart:

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.

+3
+2

Built_value, .g.dart. , json . watch.

,

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 , , , Builders Serializers.

+1

json_serialization

Team fromJson toJson seprate .

:

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.
0

, , . - ?

Many good examples were mentioned in the answers. All of them deserve to try them in real conditions.
I would like to show another example of using generated objects.

import 'dart:convert';

import 'json_objects.dart';

void main() {
  var map = jsonDecode(_json) as Map;
  var response1 = Response1.fromJson(map);
  print('Name: ' + response1.name);
  for (var car in response1.cars) {
    print('  Car name: ' + car.name + ', models: ' + car.models.join(', '));
  }
}

var _json = '''
{
  "name": "John",
  "age": 30,
  "cars": [
    { "name": "Ford", "models": ["Fiesta", "Focus", "Mustang"] },
    { "name": "BMW", "models": ["320", "X3", "X5"] },
    { "name": "Fiat", "models": ["500", "Panda"] }
  ]
}
''';

Output Result:

Name: John
  Car name: Ford, models: Fiesta, Focus, Mustang
  Car name: BMW, models: 320, X3, X5
  Car name: Fiat, models: 500, Panda

Data Models:

// Generated by 'yaml2podo'
// Version: 0.1.16
// https://pub.dev/packages/yaml2podo

class Response1 {
  final List<Response1Cars> cars;
  final String name;
  final int age;

  Response1({this.cars, this.name, this.age});

  factory Response1.fromJson(Map map) {
    return Response1(
        cars: _toList(map['cars'], (e) => Response1Cars.fromJson(e as Map)),
        name: map['name'] as String,
        age: map['age'] as int);
  }

  Map<String, dynamic> toJson() {
    var result = <String, dynamic>{};
    result['cars'] = _fromList(cars, (e) => e.toJson());
    result['name'] = name;
    result['age'] = age;
    return result;
  }
}

class Response1Cars {
  final List<String> models;
  final String name;

  Response1Cars({this.models, this.name});

  factory Response1Cars.fromJson(Map map) {
    return Response1Cars(
        models: _toList(map['models'], (e) => e as String),
        name: map['name'] as String);
  }

  Map<String, dynamic> toJson() {
    var result = <String, dynamic>{};
    result['models'] = _fromList(models, (e) => e);
    result['name'] = name;
    return result;
  }
}

List _fromList(dynamic data, dynamic Function(dynamic) toJson) {
  if (data == null) {
    return null;
  }
  var result = [];
  for (var element in data) {
    var value;
    if (element != null) {
      value = toJson(element);
    }
    result.add(value);
  }
  return result;
}

List<T> _toList<T>(dynamic data, T Function(dynamic) fromJson) {
  if (data == null) {
    return null;
  }
  var result = <T>[];
  for (var element in data) {
    T value;
    if (element != null) {
      value = fromJson(element);
    }
    result.add(value);
  }
  return result;
}

/*
# Generated by 'resp2yaml'
# Version: 0.1.16
# https://pub.dev/packages/yaml2podo

# bin/response1.json
Response1:
  "name": String
  "age": int
  "cars": List<Response1Cars>

Response1Cars:
  "name": String
  "models": List<String>
*/

0
source

Source: https://habr.com/ru/post/1679469/


All Articles