英文:
json_serializable package problematic conversion to double in flutter
问题
在反序列化期间出现了类型错误的问题,解决方法是将字符串转换为数字。您可以使用以下方式来解决这个问题:
@JsonSerializable()
class AccountFilter {
  // ...
  @JsonKey(fromJson: doubleFromString)
  double latitude = 0;
  @JsonKey(fromJson: doubleFromString)
  double longitude = 0;
  // ...
  AccountFilter(
    this.latitude,
    this.longitude,
    // ...
  );
  // ...
  factory AccountFilter.fromJson(Map<String, dynamic> json) =>
      _$AccountFilterFromJson(json);
  Map<String, dynamic> toJson() => _$AccountFilterToJson(this);
}
double doubleFromString(String value) {
  return double.tryParse(value) ?? 0.0;
}
通过在属性上使用@JsonKey注解,并指定fromJson参数,您可以自定义JSON字段到Dart属性的转换方式。在这个示例中,我们使用doubleFromString函数将字符串转换为double,并且如果转换失败,将默认值设置为0.0。
这将允许您在不更改属性名称的情况下,优雅地解决这个问题。
英文:
I have a following class:
import 'package:json_annotation/json_annotation.dart';
part 'account_filter.g.dart';
@JsonSerializable()
class AccountFilter {
  double latitude = 0;
  double longitude = 0;
  String city = "";
  String country = "";
  int minAge = 18;
  int maxAge = 99;
  int gender = 1;
  AccountFilter(
    this.latitude,
    this.longitude,
    this.city,
    this.country,
    this.minAge,
    this.maxAge,
    this.gender,
  );
  factory AccountFilter.fromJson(Map<String, dynamic> json) => _$AccountFilterFromJson(json);
  Map<String, dynamic> toJson() => _$AccountFilterToJson(this);
}
After dart run build_runner build --delete-conflicting-outputs generated file looks like this:
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'account_filter.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
AccountFilter _$AccountFilterFromJson(Map<String, dynamic> json) =>
    AccountFilter(
      (json['latitude'] as num).toDouble(), // <-- IMPORTANT!!!
      (json['longitude'] as num).toDouble(), // <-- IMPORTANT!!!
      json['city'] as String,
      json['country'] as String,
      json['minAge'] as int,
      json['maxAge'] as int,
      json['gender'] as int,
    );
Map<String, dynamic> _$AccountFilterToJson(AccountFilter instance) =>
    <String, dynamic>{
      //... some code
    };
During deserialization I receive the following error
type 'String' is not a subtype of type 'num' in type cast
Of course, the problem lies in the line
json['latitude'] as num).toDouble(),
How can I solve this problem elegantly? In my original solution I set longitude and latitude to be strings, renamed them to longitudeString and latitudeString and created two getters:
  double get latitude => double.parse(latitudeString);
  double get longitude => double.parse(longitudeString);
but I am looking for more convenient solution.
答案1
得分: 1
这是我的解决办法。
首先,我定义了一个公共方法:
double toDouble(String number) {
  return double.parse(number);
}
我对AccountFilter类进行了以下更改:
@JsonSerializable()
class AccountFilter {
  @JsonKey(fromJson: toDouble)
  double latitude;
  @JsonKey(fromJson: toDouble)
  double longitude;
  String city = "";
  String country = "";
  int minAge = 18;
  int maxAge = 99;
  int gender = 1;
AccountFilter(
    this.latitude,
    this.longitude,
    this.city,
    this.country,
    this.minAge,
    this.maxAge,
    this.gender,
  );
  factory AccountFilter.fromJson(Map<String, dynamic> json) => _$AccountFilterFromJson(json);
  Map<String, dynamic> toJson() => _$AccountFilterToJson(this);
}
基本上,我将toDouble方法设置为@JsonKey注解中的fromJson参数,用于正确解析数据。
英文:
This is how I solved it.
First, I defined public method:
double toDouble(String number) {
  return double.parse(number);
}
I've made the following changes to class AccountFilter:
@JsonSerializable()
class AccountFilter {
  @JsonKey(fromJson: toDouble)
  double latitude;
  @JsonKey(fromJson: toDouble)
  double longitude;
  String city = "";
  String country = "";
  int minAge = 18;
  int maxAge = 99;
  int gender = 1;
AccountFilter(
    this.latitude,
    this.longitude,
    this.city,
    this.country,
    this.minAge,
    this.maxAge,
    this.gender,
  );
  factory AccountFilter.fromJson(Map<String, dynamic> json) => _$AccountFilterFromJson(json);
  Map<String, dynamic> toJson() => _$AccountFilterToJson(this);
}
Basically, I set the method toDouble as a fromJson parameter in @JsonKey annotation used for correctly parsing the data.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论