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

Flutter Dart解析JSON时忽略可空引用类的必填字段

解决Dart json_serializable中可空嵌套类强制加载的问题

我定义了Delivery类,其中引用了ShippingDoc、VhcApplication等可空嵌套类(因为不确定这些类何时会有有效值)。但发现即使把这些嵌套类声明为可空,json_serializable仍会尝试加载它们的所有字段——哪怕对应的JSON字段是null或不存在,这不符合预期。比如当前VhcApplication对应的JSON值为空,但框架仍会触发它的字段加载逻辑,导致问题。

相关代码

import 'package:json_annotation/json_annotation.dart';

part 'delivery.g.dart';

enum DeliveryStatus {
  @JsonValue(0)ToBeConfirmed,
  @JsonValue(1)Ongoing,
  @JsonValue(2)Received,
  @JsonValue(3)Cancelled,
}

@JsonSerializable(explicitToJson: true)
class Delivery{
  Delivery({
    this.id,
    this.shippingDoc,
    this.shippingDocId,
    this.vhc,
    this.vhcId,
    this.aic,
    this.aicId,
    required this.status,
    required this.receivedOnDatetime,
    this.receivedBy,
    required this.receivedById,
    this.remarks,
    this.isConfirmed,
    this.isCancelled,
    this.confirmedOnDatetime,
    this.cancelledOnDatetime,
  });

  @JsonKey(name: 'id')
  String? id = "";

  @JsonKey(name: 'shipping_doc')
  ShippingDoc? shippingDoc;

  @JsonKey(name: 'shipping_doc_id')
  String? shippingDocId = "";

  @JsonKey(name: 'vhc')
  VhcApplication? vhc;

  @JsonKey(name: 'vhc_id')
  String? vhcId = "";

  @JsonKey(name: 'aic')
  VhcApplication? aic;

  @JsonKey(name: 'aic_id')
  String? aicId = "";

  @JsonKey(name: 'status')
  DeliveryStatus status = DeliveryStatus.ToBeConfirmed;

  @JsonKey(name: 'received_on_datetime')
  String receivedOnDatetime = '';

  @JsonKey(name: 'received_by')
  User? receivedBy;

  @JsonKey(name: 'received_by_id')
  String receivedById = "";

  @JsonKey(name: 'remarks')
  String? remarks = "";

  @JsonKey(name: 'is_confirmed')
  bool? isConfirmed = false;

  @JsonKey(name: 'is_cancelled')
  bool? isCancelled = false;

  @JsonKey(name: 'confirmed_on_datetime')
  String? confirmedOnDatetime = "";

  @JsonKey(name: 'cancelled_on_datetime')
  String? cancelledOnDatetime = "";

  factory Delivery.fromJson(Map<String, dynamic> json) => _$DeliveryFromJson(json);
  Map<String, dynamic> toJson() => _$DeliveryToJson(this);
}

解决方法

1. 给可空嵌套类字段添加includeIfNull: false

在@JsonKey注解中加入includeIfNull: false,这样当字段值为null时,序列化和反序列化过程都会跳过该字段,不会触发嵌套类的加载逻辑。修改后的字段示例:

@JsonKey(name: 'vhc', includeIfNull: false)
VhcApplication? vhc;

@JsonKey(name: 'aic', includeIfNull: false)
VhcApplication? aic;

@JsonKey(name: 'received_by', includeIfNull: false)
User? receivedBy;

2. 确保嵌套类的fromJson支持空值

检查VhcApplication、ShippingDoc等嵌套类的fromJson实现,确保它们能正确处理null输入。比如:

factory VhcApplication.fromJson(Map<String, dynamic>? json) {
  if (json == null || json.isEmpty) return null;
  // 正常解析逻辑
}

3. 按需关闭explicitToJson

如果你的业务场景不需要把嵌套类序列化为完整JSON对象,仅需保留ID字段,可以去掉@JsonSerializable中的explicitToJson: true。这样框架不会递归处理嵌套类,仅处理基本数据类型字段。

原理说明

json_serializable默认会处理所有声明的字段,即使是可空类型——因为explicitToJson: true会触发递归的序列化/反序列化流程。includeIfNull: false的作用是告诉框架:当字段为null时,不要对其进行任何处理,从而避免不必要的嵌套类加载操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 13:08:10