【问题标题】:flutter "could not generate 'fromJson' code for Type" error on Nullable在 Nullable 上颤动“无法为 Type 生成 'fromJson' 代码”错误
【发布时间】:2021-10-03 13:04:01
【问题描述】:

我将项目升级到 Null-Safety,但在运行 build_runner 时将属性定义为 null 时出现错误:

@JsonKey()
late Guid? colonizedStellarObjectId;

Guid 类型来自here,但我对其进行了修改以支持空安全:

import 'package:uuid/uuid.dart';
import 'package:validators/validators.dart';

/// Class that emulates as closely as possible the C# Guid type.
class Guid {
  static const String _defaultGuid = "00000000-0000-0000-0000-000000000000";

  /// The Guid whose value is the default sequence of characters that represent a 'zero-value' UUID in .Net "00000000-0000-0000-0000-000000000000"
  static Guid get defaultValue => new Guid(_defaultGuid);

  String? _value;

  /// Constructor, expects a valid UUID and will throw an exception if the value provided is invalid.
  Guid(String v) {
    _failIfNotValidGuid(v);
    _value = v;
  }

  /// Generates a new v4 UUID and returns a GUID instance with the new UUID.
  static Guid get newGuid {
    return new Guid(Uuid().v4());
  }

  /// Checks whether a value is a valid Guid
  /// Returns false if 'guid' is null or has an invalid value
  /// Returns true if guid is valid
  static bool isValid(Guid? guid) {
    if (guid == null) {
      return false;
    } else {
      return isUUID(guid.value);
    }
  }

  _failIfNotValidGuid(String? v) {
    if (v == null || v.isEmpty) {
      v = _defaultGuid;
    }
    final isInvalid = isUUID(v) == false;
    if (isInvalid) {
      throw new FlutterGuidError("Value '$v' is not a valid UUID");
    }
  }

  /// Gets the UUID value contained by the Guid object as a string.
  String get value {
    if (_value == null || _value!.isEmpty) {
      return _defaultGuid;
    } else {
      return _value!;
    }
  }

  /// Performs a case insensitive comparison on the UUIDs contained in two Guid objects.
  /// Comparison is by value and not by reference.
  bool operator ==(other) {
    return this.value.toLowerCase() == other.toString().toLowerCase();
  }

  /// Returns the hashCode.
  @override
  int get hashCode {
    return super.hashCode;
  }

  /// Gets the UUID value contained by the Guid object as a string.
  @override
  String toString() {
    return value;
  }
}

class FlutterGuidError extends Error {
  final String message;

  FlutterGuidError(this.message);
}

Could not generate `fromJson` code for `colonizedStellarObjectId`.
To support the type `Guid` you can:
* Use `JsonConverter`
  https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonConverter-class.html
* Use `JsonKey` fields `fromJson` and `toJson`
  https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/fromJson.html
  https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/toJson.html
package:astrogame_app/models/stellar/base_types/colonizable_stellar_object.dart:14:14
   ╷
14 │   late Guid? colonizedStellarObjectId;
   │              ^^^^^^^^^^^^^^^^^^^^^^^^
   ╵

我写了一个json序列化的转换器:

class GuidConverter implements JsonConverter<Guid, String> {
  const GuidConverter();

  @override
  Guid fromJson(String json) {
    return Guid(json);
  }

  @override
  String toJson(Guid object) {
    return object.toString();
  }
}

当我将属性设置为非空时,一切都很好。我在这里错过了什么?

【问题讨论】:

    标签: flutter dart null-safety


    【解决方案1】:

    我遇到过这个问题不是 json_serializable 而是 floor(它处理序列化 dart 类以存储在 sqlite 数据库中),但我会说它的机制是相同的。您的 JsonConverter 能够序列化 Guid 实例,但由于colonizedstellarobjectid 字段可以为null,toJson() 方法也应该接受null。

    那么你的 GuidConverter 必须继承 JsonConverter&lt;Guid?, String&gt;

    但通常,如果转换器甚至必须序列化 null 值,即使将其用作可空类型的输出也很有用,因此在您的情况下,基类将是 JsonConverter&lt;Guid?, String?&gt;

    例子:

    class GuidConverter implements JsonConverter<Guid?, String?> {
      const GuidConverter();
    
      @override
      Guid? fromJson(String? json) {
        if (json==null) {
          return null;      
        }
        return Guid(json);
      }
    
      @override
      String? toJson(Guid? object) {
        if (object==null) {
          return null;
        }
        return object.toString();
      }
    }
    

    【讨论】:

    • 但是toJson()方法是自动生成的,如果我编辑它,下次运行build_runner会覆盖它
    • @Daniel DirtyNative Martin :您的评论对我来说并不清楚(这让人怀疑我还没有真正理解您的问题),但我验证了 JsonConverter 必须能够管理空值。我希望这个例子能阐明我的意思
    • 无论如何,您选择通过特殊的 JsonConverter 序列化 Guid 而不是使用 @JsonSerializable 注释 Guid 类是否有原因? JsonConverter 是在您不访问类的源代码时设计的,但是在您的情况下,如果我没记错的话,您编写了此版本的 Guid 类,那么您可以对其进行注释。如果您想尝试这种方法,请记住包含“Guid?colonized..”字段的类必须使用@JsonSerializable(explicitToJson: true) 进行注释,否则将无法创建正确的代码(explicitToJson 的文档)解释原因)
    • 我使用转换器是因为我想从字符串而不是映射反序列化 Guid。
    • 好的,我解决了。我已经写了一个接受 Guid 的转换器?但我只将它添加到一个抽象类中,而不是在继承的类中......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 1970-01-01
    • 2022-11-01
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 2021-02-11
    相关资源
    最近更新 更多