冻结了如何在***模型上分配我自己的 JsonConverter?

Posted

技术标签:

【中文标题】冻结了如何在***模型上分配我自己的 JsonConverter?【英文标题】:freezed how to assign my own JsonConverter on top level model? 【发布时间】:2021-12-10 17:33:18 【问题描述】:

我已经冻结了模型(简化):

part 'initial_data_model.freezed.dart';
part 'initial_data_model.g.dart';

@freezed
class InitialDataModel with _$InitialDataModel 
  const factory InitialDataModel() = Data;

  const factory InitialDataModel.loading() = Loading;

  const factory InitialDataModel.error([String? message]) = Error;

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

文档说明了如何在字段而不是模型本身上分配自定义转换器

我从后端和 api_provider 的某个地方得到了 jsonreturn InitialDataModel.fromJson(json); 我无法控制 json 结构,没有“runtimeType”和其他愚蠢的冗余东西

当我想从 json 创建模型时,我调用 fromJson 我有这个

flutter: CheckedFromJsonException
Could not create `InitialDataModel`.
There is a problem with "runtimeType".
Invalid union type "null"!

好的,再次 我有api_provider

final apiProvider = Provider<_ApiProvider>((ref) => _ApiProvider(ref.read));

class _ApiProvider 
  final Reader read;

  _ApiProvider(this.read);

  Future<InitialDataModel> fetchInitialData() async 
    final result = await read(repositoryProvider).send('/initial_data');
    return result.when(
      (json) => InitialDataModel.fromJson(json),
      error: (e) => InitialDataModel.error(e),
    );
  

你可能会看到我正在尝试从 json 创建 InitialDataModel

这行抛出了我上面提到的错误

我不明白如何从 json 创建 InitialDataModel,现在在我的示例中它只是空模型,没有字段

(json) =&gt; InitialDataModel.fromJson(json),json 这里是 Map,即使我传递简单的空地图 而不是真正的 json 对象,它也会显示错误

【问题讨论】:

您是否使用serializable 包来生成fromJson 方法? 为什么您需要为整个模型定制转换器?使用自定义转换器注释每个非原始字段就足够了 您需要将json_serializable 添加到您的pubspec dev_dependencies。如果您的冻结类中有 fromJson 工厂构造函数,则此包将生成 json 转换所需的代码。并且您的非原始字段必须使用自定义 json-converters 进行注释 您的类型似乎有问题。转换仅适用于原始类型,如 int、string、double 或带注释的非原始类型。因此,您必须为CountryModelCityModel 编写一个json 转换器并相应地注释这些字段。 您要转换哪种类型的json 变量? String 还是 Map&lt;String, dynamic&gt;?如果是String,则必须先转换flutter.dev/docs/development/data-and-backend/… 【参考方案1】:

最简单的解决方案是使用正确的构造函数而不是 _$InitialDataModelFromJson。示例:

@freezed
class InitialDataModel with _$InitialDataModel 
  const factory InitialDataModel() = Data;

  ...

  factory InitialDataModel.fromJson(Map<String, dynamic> json) => Data.fromJson(json);

当然,缺点是只能在确定自己拥有正确的 json 时才能使用 fromJson,这不是很好。我实际上不推荐这种方式,因为它给调用者留下了检查有效性和调用正确构造函数的负担。


另一种可能是最好的解决方案是遵循documentation 并创建一个自定义转换器,即使这需要您有两个单独的类。


否则,您可以选择不同的方法并将数据类与联合分开,这样您将拥有一个仅用于请求状态的联合和一个用于成功响应的数据类:

@freezed
class InitialDataModel with _$InitialDataModel 
  factory InitialDataModel(/* here go your attributes */) = Data;

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


@freezed
class Status with _$Status 
  const factory Status.success(InitialDataModel model) = Data;
  const factory Status.loading() = Loading;
  const factory Status.error([String? message]) = Error;


然后

[...]
    return result.when(
      (json) => Status.success(InitialDataModel.fromJson(json)),
      error: (e) => Status.error(e),
    );
[...]

【讨论】:

天啊,我救了我的命!!!!我花了一整天的时间,你是完全正确的,我刚刚将=&gt; _$InitialDataModelFromJson(json); 更改为=&gt; _$Data.fromJson(json);,它现在正在工作!我的真实代码比这个例子复杂得多,但我没有更改任何额外的行,原因是在构造函数中,正如你所说,非常感谢 太好了!无论如何,我改进了我的答案,以添加一些意见和另一种解决方案,以防其他人需要这个

以上是关于冻结了如何在***模型上分配我自己的 JsonConverter?的主要内容,如果未能解决你的问题,请参考以下文章

如何纠正/改进我的 CNN 模型?如何处理验证准确性冻结问题?

如何找到冻结模型的输入和输出节点

当我调用 JsonConvert.DeserializeObject() 时,为啥将 JArray 分配给 var 失败?

如何冻结拥抱脸模型?

当我尝试在 Armv8 程序集中分配数组时执行冻结

当Eclipse构建我的工作区时,它会冻结