'Dart json_serializable defaultValue for Map with Enum Value
My main issue is that i want to prevent the field value to get null when creating an object from parsing json. The field is a Map<String, enum>.
Example code:
import 'package:json_annotation/json_annotation.dart';
enum Letter{ A, B,C}
@JsonSerializable()
class example{
@JsonKey(defaultValue: {
'C': Letter.C
})
Map<String, Letter> letters = {
'A': Letter.A,
'B':Letter.B
};
}
Error occours when running:
flutter pub run build_runner build
The error message is:
Error running JsonSerializableGenerator Error with
@JsonKeyonletters.defaultValueisMap > Letter, it must be a literal.
Found this: https://github.com/google/json_serializable.dart/issues/361
But if I try to use the converter methods I run into other issues, so trying to solve the root issue.
Solution 1:[1]
Use name property and byName method of enums
import 'dart:convert';
void main() {
Person raj = Person(name: 'Raj', favIcecream: Icecream.pista);
print(raj.toJson());
Person rajV2 = Person.fromJson(raj.toJson());
print(rajV2.toJson());
final isBothInstanceEqual = raj == rajV2;
print('> Both instancecs are equal is $isBothInstanceEqual');
}
enum Icecream {
vanilla,
pista,
strawberry,
}
class Person {
String name;
Icecream favIcecream;
Person({
required this.name,
required this.favIcecream,
});
Map<String, dynamic> toMap() {
return {
'name': name,
'favIcecream': favIcecream.name, // <- this is how you should save
};
}
factory Person.fromMap(Map<String, dynamic> map) {
return Person(
name: map['name'] ?? '',
favIcecream: Icecream.values.byName(map['favIcecream']), // <- back to enum
);
}
String toJson() => json.encode(toMap());
factory Person.fromJson(String source) => Person.fromMap(json.decode(source));
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is Person &&
other.name == name &&
other.favIcecream == favIcecream;
}
@override
int get hashCode => name.hashCode ^ favIcecream.hashCode;
}
Solution 2:[2]
A solution that works on a minimal scale.
pupspec.yaml:
name: playground
description: A simple command-line application.
environment:
sdk: '>=2.8.1 <3.0.0'
dependencies:
json_annotation: ^3.0.1
dev_dependencies:
build_runner: ^1.10.0
json_serializable: ^3.3.0
pedantic: ^1.9.0
playground.dart:
import 'package:json_annotation/json_annotation.dart';
part 'playground.g.dart';
enum Letter{ A, B, C}
@JsonSerializable()
class example{
example(){}
@JsonKey(fromJson: parseMap, toJson: toStringMap)
Map<String, Letter> letters = {
'A': Letter.A,
'B':Letter.B
};
factory example.fromJson(Map<String, dynamic> json) => _$exampleFromJson(json);
Map<String, dynamic> toJson() => _$exampleToJson(this);
static Map<String, Letter> parseMap(Map<String,String> m){
if(m==null){
return {
'C': Letter.C
};
}
Map<String, Letter> result ={};
for(String key in m.keys){
result[key]=Letter.values.firstWhere((e) => e.toString() == m[key]);
}
return result;
}
static Map<String, String> toStringMap(Map<String,Letter> m){
if(m==null){
return {
'C': 'C'
};
}
Map<String, String> result ={};
for(String key in m.keys){
result[key]=m[key].toString();
}
return result;
}
}
void main(List<String> arguments) {
var ex = example.fromJson({});
print(ex.letters.values);
var ex2 = new example();
var m =ex2.toJson();
print(m);
var ex3 = new example();
ex3.letters=null;
var m2 =ex3.toJson();
print(m2);
}
Run:
pub run build_runner build
dart .\bin\playground.dart
Output:
(Letter.C)
{letters: {A: Letter.A, B: Letter.B}}
{letters: {C: C}}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Anoop Thiruonam |
| Solution 2 | Chris_S |
