Пользовательский JsonConverter с разными типами в toJson и fromJson

Чтобы читать и записывать данные с отношениями к PocketBase API, мне нужны пользовательские иtoJsonметоды де/сериализации его для моих моделей:

      
@freezed
class MyModel with _$MyModel {
  const factory MyModel({
    String name,
    @RelationsConverter() List<Relation>? relations,
  }) = _MyModel;

  factory MyModel.fromJson(Map<String, Object?> json) => _$MyModelFromJson(json);
}

@freezed
class Relation with _$Relation {
  const factory Relation({
    required String id,
    String name,
  }) = _Relation;

  factory Relation.fromJson(Map<String, Object?> json) => _$RelationFromJson(json);
}

Данные Json при чтении модели из PocketBase с полями «имя» и «отношения», которая содержит список отношений к какой-то другой модели, могут выглядеть так (с полемexpand=relationsнабор параметров запроса):

      {
    "name": "A model",
    "relations": [
        "abc123",
        "def456"
    ],
    "expand": {
        "relations": [
            {
                "id": "abc123",
                "name": "Relation A"
            },
            {
                "id": "def456",
                "name": "Relation B"
            }
        ]
    }
}

Перед преобразованием данных в мои модели я преобразовываю данные, чтобы они выглядели так и могли быть легко десериализованы:

      {
    "name": "A model",
    "relations": [
        {
            "id": "abc123",
            "name": "Relation A"
        },
        {
            "id": "def456",
            "name": "Relation B"
        }
    ]
}

Однако при обновлении/создании данных эта форма нежелательна, мне она нужна в этой форме:

      {
    "name": "An updated model with a new relation",
    "relations": [
        "abc123",
        "def456",
        "xyz999"
    ]
}

Я надеялся, что это будет тривиально с пользовательским конвертером. Ttype используется в качестве заполнителя, так как это моя основная проблема:

      class RelationsConverter implements JsonConverter<Relation, T> {
  const RelationsConverter();

  @override
  Relation fromJson(K json) => ...

  @override
  T toJson(Skill data) => ...
}

@freezed
class MyModel with _$MyModel {
  const factory MyModel({
    String name,
    @RelationsConverter() List<Relation>? relations,
  }) = _MyModel;

  factory MyModel.fromJson(Map<String, Object?> json) => _$MyModelFromJson(json);
}

Проблема здесь в том, что покаjsonFromпередается карта, toJson возвращает строку:

      Relation fromJson(Map<String, dynamic> json) => Relation.fromJson(json);

String toJson(Relation relation) => relation.id;

Однако мне нужно передать определенный тип как для to-, так и для fromJson в JsonConverter:class RelationsConverter implements JsonConverter<Relation, [Map or String]>

я тоже не могу пропуститьfromJson(что я бы хотел), потому что интерфейс заставляет меня реализовать оба метода.

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

1 ответ

немного поздно отвечать на вопрос, но, поскольку я столкнулся с подобной проблемой, я нашел обходной путь с помощью JsonConverter

например, если вы конвертируете переменную someBoolean bool -> string при отправке данных в API, а API отправляет someBoolean как bool обратно, тогда у вас будет bool->string при отправке и bool->bool при получении.

конвертер json будет выглядеть примерно так:

      class BoolConverter implements JsonConverter<bool, dynamic> {
  const BoolConverter ();

  // use dynamic to determine runtime type
  @override
  bool fromJson(dynamic json) {
    if (json == null) return false;
    if (json is bool) return json;
    return json is String ? json.toBoolean() : false;
  }

  @override
  String toJson(bool value) {
    return value ? 'true' : 'false';
  }

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