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

Flutter Dart中用json_serializable解析类型不统一的JSON

解决json_serializable解析混合类型字段的问题

问题分析

第三方API返回的retro字段类型不统一:大部分是布尔值(true/false),但存在空字符串("")的情况,直接用as bool强制转换会抛出类型转换异常。

解决方案

方法一:自定义字段转换函数(推荐)

利用json_serializable的@JsonKey注解,为retro字段指定自定义转换逻辑,兼容布尔值和空字符串类型。

修改后的实体类代码:

import 'package:json_annotation/json_annotation.dart';

@JsonSerializable()
class UserItem {
  int id;
  String email;
  String gender;
  @JsonKey(name: 'ip_address')
  String ipAddress;
  String name;
  
  // 为retro字段指定自定义转换函数
  @JsonKey(fromJson: _retroFromJson)
  bool retro;

  UserItem(this.id, this.email, this.gender, this.ipAddress, this.name, this.retro);

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

  Map<String, dynamic> toJson() => _$UserItemToJson(this);

  // 自定义转换函数:处理布尔值、空字符串,默认返回false
  static bool _retroFromJson(dynamic value) {
    if (value is bool) {
      return value;
    } else if (value is String) {
      // 空字符串视为false,可根据业务需求调整
      return value.isNotEmpty ? bool.tryParse(value) ?? false : false;
    }
    // 其他未知类型默认返回false
    return false;
  }
}

// 以下部分可通过build_runner自动生成,无需手动修改
UserItem _$UserItemFromJson(Map<String, dynamic> json) => UserItem(
  json['id'] as int,
  json['email'] as String,
  json['gender'] as String,
  json['ip_address'] as String,
  json['name'] as String,
  UserItem._retroFromJson(json['retro']),
);

Map<String, dynamic> _$UserItemToJson(UserItem instance) => <String, dynamic>{
  'id': instance.id,
  'email': instance.email,
  'gender': instance.gender,
  'ip_address': instance.ipAddress,
  'name': instance.name,
  'retro': instance.retro,
};

方法二:手动修改生成的解析函数

如果不想添加自定义转换函数,也可以直接修改_$UserItemFromJson中retro字段的解析逻辑,对类型进行判断:

UserItem _$UserItemFromJson(Map<String, dynamic> json) => UserItem(
  json['id'] as int,
  json['email'] as String,
  json['gender'] as String,
  json['ip_address'] as String,
  json['name'] as String,
  // 增加类型判断,兼容布尔值和空字符串
  json['retro'] is bool 
      ? json['retro'] as bool 
      : (json['retro'] as String).isEmpty 
          ? false 
          : bool.tryParse(json['retro']) ?? false,
);

注意:这种方法的缺点是,每次通过build_runner重新生成代码时,修改的内容会被覆盖,需要重新调整。

验证效果

修改后重新运行flutter pub run build_runner build生成代码,即可正常解析包含空字符串retro字段的JSON数据,不会再抛出类型转换异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 23:47:22