I upgraded my project to Null-Safety but I'm getting an error when I define a property as null when running the build_runner:
@JsonKey()
late Guid? colonizedStellarObjectId;
The type Guid is from here, but I modified it to support null-safety:
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;
│ ^^^^^^^^^^^^^^^^^^^^^^^^
╵
I have written a converter for the json serialization:
class GuidConverter implements JsonConverter<Guid, String> {
const GuidConverter();
@override
Guid fromJson(String json) {
return Guid(json);
}
@override
String toJson(Guid object) {
return object.toString();
}
}
When I set the property as not-null, everything is fine. What am I missing here?
I had experience of this problem not with json_serializable but with floor (which deals with serializing dart classes for storage in a sqlite database), but the mechanism I would say that it is the same. Your JsonConverter is able to serialize a Guid instance, but since the colonizedstellarobjectid field can be null, the toJson() method should also accept null.
Then your GuidConverter has to subclass JsonConverter<Guid?, String>
.
However often, if a converter must even serialize the null value, is useful to use even as output a nullable type, so in your case the base class would be JsonConverter<Guid?, String?>
.
Example:
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();
}
}