Пользовательский 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"
]
}
Я надеялся, что это будет тривиально с пользовательским конвертером. T
type используется в качестве заполнителя, так как это моя основная проблема:
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';
}
}