You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter JSON序列化报错求助:'String'类型无法转换为'num?'类型

解决Flutter JSON序列化中String转num的类型转换错误

看样子你碰到的问题是:虽然示例API返回的lat/lng是数字类型,但实际请求时这些字段可能偶尔以字符串格式的数字(比如"50.754")返回,而自动生成的序列化代码直接强转成num?,导致类型不匹配报错。下面给你几个实用的解决方案:

方案1:自定义JSON转换器兼容混合类型

我们可以写一个通用转换器,同时支持数字和字符串转double,不管API返回哪种格式都能适配:

首先定义转换器类:

import 'package:json_annotation/json_annotation.dart';

class StringToDoubleConverter implements JsonConverter<double?, dynamic> {
  const StringToDoubleConverter();

  @override
  double? fromJson(dynamic json) {
    // 数字类型直接转double
    if (json is num) {
      return json.toDouble();
    } 
    // 字符串类型尝试解析成double
    else if (json is String) {
      return double.tryParse(json);
    }
    // 其他情况返回null
    return null;
  }

  @override
  dynamic toJson(double? object) => object;
}

然后把转换器应用到CarModel上,有两种方式可选:

方式A:全局应用到整个类

@JsonSerializable(converters: [const StringToDoubleConverter()])
class CarModel extends Car {
  // 你的类原有代码
}

方式B:单独应用到lat/lng字段

@JsonSerializable()
class CarModel extends Car {
  const CarModel({
    super.id,
    super.brand,
    super.model,
    super.color,
    super.registration,
    super.year,
    super.ownerId,
    super.lat,
    super.lng,
  });

  @JsonKey(name: '_id')
  @override
  String? get id;

  @JsonKey(fromJson: _stringToDouble)
  @override
  double? get lat;

  @JsonKey(fromJson: _stringToDouble)
  @override
  double? get lng;

  factory CarModel.fromJson(Map<String, dynamic> json) => _$CarModelFromJson(json);
  Map<String, dynamic> toJson() => _$CarModelToJson(this);
}

// 单独的转换函数
double? _stringToDouble(dynamic value) {
  if (value is num) {
    return value.toDouble();
  } else if (value is String) {
    return double.tryParse(value);
  }
  return null;
}

方案2:临时调试修复(不推荐长期使用)

虽然不建议手动修改自动生成的.g.dart文件,但如果只是临时调试,可以把报错的两行改成宽松的转换逻辑:

lat: json['lat'] is String ? double.tryParse(json['lat'] as String) : (json['lat'] as num?)?.toDouble(),
lng: json['lng'] is String ? double.tryParse(json['lng'] as String) : (json['lng'] as num?)?.toDouble(),

注意:下次运行build_runner命令时,这个修改会被覆盖,所以优先选方案1。

额外排查建议

  • 抓包确认API返回的所有数据中,lat/lng是否存在混合类型(部分数字、部分字符串),比如用Postman或Charles查看实际请求结果。
  • 如果API是你可控的,最好统一返回数字类型,从根源避免类型不一致的问题。

最后,修改完代码后别忘了重新生成序列化文件:

flutter pub run build_runner build

内容的提问来源于stack exchange,提问作者szakes1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 22:02:50