Как преобразовать карту в список ключей

Предположим, у меня есть следующая модель (с использованием замороженного):

@freezed
class User with _$User {
  const factory User({
    required UserID id,
    required List<String> categories,
  }) = _User;

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}

Я хотел бы десериализовать эту модель из объекта JSON, который выглядит следующим образом:

{
  "id": "1234",
  "categories": {
    "A": true,
    "B": true
  }
}

Очевидно, что сериализация по умолчанию не работает, поэтому я попробовал реализовать собственную JsonConverter:

class ListMapConverter<K, V> implements JsonConverter<List<K>, Map<K, V>> {
  const ListMapConverter(this._value);

  final V _value;

  @override
  List<K> fromJson(Map<K, V> json) => json.keys.toList();

  @override
  Map<K, V> toJson(List<K> object) => {for (final e in object) e: _value};
}

Я аннотировал свойство модели следующим образом:

@ListMapConverter<String, bool>(true) required List<String> categories

Это не работает, и пользовательский конвертер не используется в сгенерированном выводе:

_$UserImpl _$$UserImplFromJson(Map<String, dynamic> json) => _$UserImpl(
      id: UserID.fromJson(json['id'] as String),
      categories: (json['categories'] as List<dynamic>)
          .map((e) => e as String)
          .toList(),
    );

Map<String, dynamic> _$$UserImplToJson(_$UserImpl instance) =>
    <String, dynamic>{
      'id': instance.id,
      'categories': instance.categories,
    };

Как я могу это исправить? Есть ли лучший способ конвертировать карты в списки и наоборот, используя замороженный/json_serializable? Спасибо.

Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
1
0
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Кажется, проблема в том, чтобы json_serializable молча игнорировать ваш универсальный конвертер. Кроме того, json_serializable не поддерживает преобразователи с аргументами конструктора, см. этот выпуск.

Обходной путь — сделать ваш конвертер неуниверсальным и использовать именованные конструкторы для предоставления переменной экземпляра _value:

class ListMapConverter implements JsonConverter<List<String>, Map<String, bool>> {
  // const ListMapConverter(this._value);
  const ListMapConverter.zero() : _value = false;
  const ListMapConverter.one() : _value = true;

  final bool _value;

  @override
  List<String> fromJson(Map<String, bool> json) => json.keys.toList();

  @override
  Map<String, bool> toJson(List<String> object) => {for (final e in object) e: _value};
}

Затем вы можете использовать аннотацию: @ListMapConverter.one().

Учитывая все это, возможно, было бы проще расширить класс User вручную, добавив метод toJson и конструктор фабрики fromJson.

Вы все равно можете использовать freezed для создания других удобных методов, например copyWith и т. д.

Поддерживаются ли дженерики? Я только что попытался удалить общий аргумент V и заменить его просто логическим значением, но он все равно не работает.

katkak 02.07.2024 11:39

Ну, он просто попробовал это без каких-либо общих аргументов, и это, похоже, работает. Это неудачно. Ну что ж :)

katkak 02.07.2024 11:42

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