In order to read from and write data with relations to the PocketBase API I need custom fromJson and toJson methods to de/serialize it to my models:
@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);
}
The Json data when reading a model from PocketBase with the fields "name" and "relations", which contains a list of relations to some other model might look like this (with the expand=relations query parameter set):
{
    "name": "A model",
    "relations": [
        "abc123",
        "def456"
    ],
    "expand": {
        "relations": [
            {
                "id": "abc123",
                "name": "Relation A"
            },
            {
                "id": "def456",
                "name": "Relation B"
            }
        ]
    }
}
Before converting the data to my models, I transform the data so it looks like this and can be easily deserialized:
{
    "name": "A model",
    "relations": [
        {
            "id": "abc123",
            "name": "Relation A"
        },
        {
            "id": "def456",
            "name": "Relation B"
        }
    ]
}
When updating/creating data however, this form is not desired, I need it in this form:
{
    "name": "An updated model with a new relation",
    "relations": [
        "abc123",
        "def456",
        "xyz999"
    ]
}
I was hoping this would be trivial with a custom converter. The T type is used as a placeholder since this is my main problem:
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);
}
The problem here is that while jsonFrom is passed a Map, toJson returns a String:
Relation fromJson(Map<String, dynamic> json) => Relation.fromJson(json);
String toJson(Relation relation) => relation.id;
However I need to pass a specific type for both to-and fromJson to JsonConverter:
class RelationsConverter implements JsonConverter<Relation, [Map or String]>
I neither can omit fromJson (which I'd like to) because the interface forces me to implement both methods.
How can I solve this? I I could get around my custom transforming if the incoming data and solve this in a converter, this would also be nice.
                        
it's a little late to answer the question but since i encountered a similar issue, i found a workaround to it using JsonConverter
for example, if you are converting a variable someBoolean bool -> string when sending data to the api and the api sends someBoolean as bool back then you would have bool->string while sending and bool->bool while receiving.
the json converter would look something like this: