如何为json可序列化的对象设置默认值?

问题描述 投票:0回答:3

我想为

AvailableService
设置默认值。对于原语来说它足够简单。我将如何使用自定义对象来做到这一点

class Submenu extends Equatable {
     @JsonKey(defaultValue: "")
        final String name;
      @JsonKey(defaultValue: new AvailableService(false,false,false,false))
        final AvailableService availableService;
    
    }

自定义对象:

AvailableService {
bool supportsDelivery;
  bool supportsTableService;
  bool supportsCollection;
  bool supportsChat;
 
}

编译时错误是

Arguments of a constant creation must be constant expressions.
Try making the argument a valid constant, or use 'new' to call the constructor
flutter dart
3个回答
11
投票

一般来说,作为注解参数,你只能传递常量,因此你不能传递用 new 创建的对象,而只能传递 const 构造函数(你应该将所有的 AvailableService 字段定义为 Final,并定义一个 const 构造函数)。 然而,在 json_Serialized 中,defaultValue 目前有一些额外的限制:

  • 您甚至不能使用通过 const 构造函数创建的自定义对象(或者您会收到错误“它必须是文字”)。有一个删除此约束的开放请求:#741 - Const as default value
  • 作为defaultValue,只允许使用文字;然后,您可以传递一个 Map 字面值(即:
    @JsonKey(defaultValue: {"supportsDelivery" : false, "supportsTableService" : false, /* etc */})
    ),但即使这种可能性目前也仅适用于具有 Map 类型的字段的默认值,而不适用于具有自定义类型的字段(如可用服务)。在这种情况下,您不会收到错误,但永远不会使用 defaultValue(通过查看 .g.dart 文件中生成的代码,您可以理解原因)。对于此问题也有开放请求:#676 - 允许默认值编码为 JSON#789 - 如何为嵌套 JSON 对象设置默认值?

因此,在跟进上述请求之前,我找到的唯一解决方法是处理

fromJson()
工厂中的 defaultValue:

  factory AvailableService.fromJson(Map<String, dynamic> json) =>
      json != null 
      ? _$AvailableServiceFromJson(json)
      : AvailableService(false, false, false, false);

简而言之,

JsonKey.defaultValue
目前只支持文字——甚至不接受常量——并且只能用于原始类型字段(或List、Map、Set)的默认值。


6
投票

从json_serialized 5开始,生成的fromJson使用构造函数的默认参数,所以你可以这样做

@JsonSerializable()
class Cart {
  final List<int> items;

  const Cart({
    this.items = const [],
  });

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

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

@JsonSerializable()
class User {
  final Cart cart;

  const User({
    this.cart = const Cart(),
  });

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

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

然后

Cart.fromJson({}).items
User.fromJson({}).cart.items
会给你
[]


0
投票

对于那些想要使用常量来更优化地管理源代码的人。

因为如果标签不是“字面量”,则

json_serializable
处理程序将在将标签传递给
defaultValue
时尝试调用“常量”函数。

所以你需要做的是创建一个返回默认值的静态函数:

@JsonSerializable(explicitToJson: true)
class MetadataDto {
  @JsonKey(name: "version_name")
  final String versionName;

  @JsonKey(name: "version_code")
  final int versionCode;

  const MetadataDto({
    this.versionName = "1.0.0",
    this.versionCode = 1,
  });

  static MetadataDto kDefault() => const MetadataDto();
}

在另一个实例中,将单例函数设置为

defaultValue
正如其名称一样(不带括号)。

@JsonSerializable(explicitToJson: true)
class ContentDto {
  @JsonKey(name: "metadata", defaultValue: MetadataDto.kDefault)
  final MetadataDto info;

  const ContentDto({
     required this.info,
  });
}

运行后检查

.g.dart
(生成的文件)
build_runner

ContentDto _$ContentDto FromJson(Map<String, dynamic> json) =>
    ContentDto(
      info: json['metadata'] == null
          ? MetadataDto.kDefault()
          : MetadataDto.fromJson(json['metadata'] as Map<String, dynamic>),
    );

就是这样。

© www.soinside.com 2019 - 2024. All rights reserved.