Dart json_serializable defaultValue для карты со значением Enum

Моя основная проблема заключается в том, что я хочу, чтобы значение поля не получило нулевое значение при создании объекта из синтаксического анализа json. Поле представляет собой Map.

Пример кода:

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
    };
}

Ошибка возникает при запуске:

flutter pub run build_runner build

Сообщение об ошибке:

Ошибка запуска JsonSerializableGenerator Ошибка с @JsonKey наletters. defaultValue является Map > Letter, это должно быть буквальное значение.

Нашел это:https://github.com/google/json_serializable.dart/issues/361

Но если я попытаюсь использовать методы конвертера, я столкнусь с другими проблемами, поэтому попытаюсь решить основную проблему.

2 ответа

Используйте свойство name и метод перечислений byName

      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;
}

Решение, работающее в минимальном масштабе.

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

игровая площадка.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);
}

Бегать:

pub run build_runner build
dart .\bin\playground.dart

Выход:

(Буква.C)
{письма: {A: Буква.A, B: Буква.B}}
{буквы: {C: C}}

Другие вопросы по тегам