Dart使用json_serializable

时间:2019-11-22 22:42:19

标签: flutter dart

  • 我正在geocoder library的帮助下工作。
  • 当我收到Address时,我想将其保存为firebase
    firestore
    作为用户(对象)属性,但要做到这一点,我需要
    序列化地址(将其转换为地图)。
  • 当前,我正在使用json_serializable来解析/映射我的 用户类别。
  • 因为Address是地理编码器库中的一类,所以我很难将其解析到地图中/从地图中解析出来,因为这是由json_serializable处理的。

这是我的User类:

    import 'package:geocoder/model.dart';
    import 'package:json_annotation/json_annotation.dart';

    import './resource.dart';

    part 'user.g.dart';

    @JsonSerializable()
    class User extends Resource {
       User(this.email, this.name);

       String email;
       String name;
       List<Address> addresses;

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

       Map<String, dynamic> toJson() => _$UserToJson(this);
    }
  • 我尝试创建一个名为UserAddress的新类,其父类将为类似于以下地址,但出现错误
  

构造函数返回的类型“ Address”不是预期的类型“ UserAddress”。dart(invalid_cast_new_expr)

在命名的构造函数UserAddress.fromJson中:

import 'package:geocoder/geocoder.dart';
import 'package:json_annotation/json_annotation.dart';

part 'user-address.g.dart';

@JsonSerializable()
class UserAddress extends Address {
  UserAddress();

  factory UserAddress.fromJson(Map<String, dynamic> json) =>
      Address.fromMap(json);

  Map<String, dynamic> toJson() => this.toMap();
}

请给我一些选择,以实现与地图之间的解析。

1 个答案:

答案 0 :(得分:1)

如果我答对了,您想用自己的装饰图书馆的课。您可以使用@JsonKey注释来设置(en)解码库的Address对象的函数。

import 'dart:convert';

import 'package:geocoder/geocoder.dart';
import 'package:json_annotation/json_annotation.dart';

part 'user_address.g.dart';

@JsonSerializable()
class UserAddress {
  UserAddress(this.address, this.oneMoreField);

  @JsonKey(fromJson: _addressFromJson, toJson: _addressToJson)
  final Address address;
  final int oneMoreField;

  factory UserAddress.fromJson(Map<String, dynamic> json) => _$UserAddressFromJson(json);
  Map<String, dynamic> toJson() => _$UserAddressToJson(this);
}

String _addressToJson(Address address) => jsonEncode(address.toMap());
Address _addressFromJson(String json) => Address.fromMap(jsonDecode(json));

用法示例:

final testUserAddress = UserAddress(Address(
  addressLine: 'test',
  coordinates: Coordinates(10, 20)
), 1);

final json = testUserAddress.toJson();
print(json);

final decoded = UserAddress.fromJson(json);

打印:

{address: {"coordinates":{"latitude":10.0,"longitude":20.0},"addressLine":"test","countryName":null,"countryCode":null,"featureName":null,"postalCode":null,"locality":null,"subLocality":null,"adminArea":null,"subAdminArea":null,"thoroughfare":null,"subThoroughfare":null}, oneMoreField: 1}

如您所见,所有嵌套对象都被正确编码。

UPD :通过继承进行操作时,您必须将所有基类的字段传递给超级构造函数,并使用@JsonKey批注覆盖嵌套对象的字段:

@JsonSerializable()
class UserAddress extends Address {
  UserAddress({String addressLine, String countryName, this.coordinates, this.oneMoreField}) 
    : super(addressLine: addressLine, countryName: countryName);

  @override
  @JsonKey(fromJson: _coordinatesFromJson, toJson: _coordinatesToJson)
  final Coordinates coordinates;

  final int oneMoreField;

  factory UserAddress.fromJson(Map<String, dynamic> json) => _$UserAddressFromJson(json);
  Map<String, dynamic> toJson() => _$UserAddressToJson(this);
}

String _coordinatesToJson(Coordinates coordinates) => jsonEncode(coordinates.toMap());
Coordinates _coordinatesFromJson(String json) => Coordinates.fromMap(jsonDecode(json));

结果:

{addressLine: test, countryName: null, coordinates: {"latitude":10.0,"longitude":20.0}, oneMoreField: 1}

但是在这种情况下,我建议对继承使用合成。