'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 @JsonKey on letters. defaultValue is Map > 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