You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart适配PocketBase的双向异构JsonConverter实现难题

解决PocketBase API序列化/反序列化的转换器兼容问题

针对你遇到的JsonConverter泛型约束限制,没法分别指定反序列化输入(Map)和序列化输出(String)的问题,这里有几种实用的解决方案:

方案1:自定义双向转换器+适配类

先绕开标准JsonConverter的单泛型限制,定义一个支持不同输入输出类型的转换器接口,再写适配类把它套成标准转换器可用的形式:

  1. 定义双向转换器接口
public interface TwoWayConverter<In, Out> {
    Out from(In input);
    In to(Out output);
}
  1. 实现Relation专属的转换逻辑
public class RelationTwoWayConverter implements TwoWayConverter<Map<String, Object>, Relation> {
    @Override
    public Relation from(Map<String, Object> expandMap) {
        // 把expand返回的Map转成Relation实例
        return new Relation(
            (String) expandMap.get("id"),
            (String) expandMap.get("name")
            // 其他字段按需映射
        );
    }

    @Override
    public Map<String, Object> to(Relation relation) {
        // 返回仅包含id的Map,适配后续序列化逻辑
        Map<String, Object> result = new HashMap<>();
        result.put("id", relation.getId());
        return result;
    }
}
  1. 写适配类对接标准JsonConverter
public class RelationConverterAdapter implements JsonConverter<Relation> {
    private final TwoWayConverter<Map<String, Object>, Relation> converter;
    private final Gson gson = new Gson();

    public RelationConverterAdapter(TwoWayConverter<Map<String, Object>, Relation> converter) {
        this.converter = converter;
    }

    @Override
    public Relation fromJson(JsonElement jsonElement) throws JsonParseException {
        Map<String, Object> expandMap = gson.fromJson(jsonElement, new TypeToken<Map<String, Object>>(){}.getType());
        return converter.from(expandMap);
    }

    @Override
    public JsonElement toJson(Relation relation) throws JsonSerializationException {
        // 序列化时直接输出id字符串
        return new JsonPrimitive(relation.getId());
    }
}

方案2:用TypeAdapter直接突破泛型限制(推荐)

如果用Gson这类序列化库,直接用TypeAdapter比JsonConverter灵活得多,它不需要强制输入输出类型统一:

public class RelationTypeAdapter extends TypeAdapter<Relation> {
    @Override
    public void write(JsonWriter out, Relation relation) throws IOException {
        // 写操作:直接输出Relation的id字符串
        out.value(relation.getId());
    }

    @Override
    public Relation read(JsonReader in) throws IOException {
        // 读操作:把expand返回的整个对象Map转成Relation实例
        in.beginObject();
        Map<String, Object> data = new HashMap<>();
        while (in.hasNext()) {
            String key = in.nextName();
            switch (key) {
                case "id":
                    data.put(key, in.nextString());
                    break;
                case "name":
                    data.put(key, in.nextString());
                    break;
                // 其他字段按需处理,不需要的直接跳过
                default:
                    in.skipValue();
                    break;
            }
        }
        in.endObject();
        return new Relation((String) data.get("id"), (String) data.get("name"));
    }
}

然后注册这个TypeAdapter到你的Gson实例里:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(Relation.class, new RelationTypeAdapter())
    .create();

这样反序列化时会自动把expand里的对象转成Relation实例,序列化时自动把Relation转成id字符串,完全替代预处理逻辑。

方案3:注解绑定序列化/反序列化器(Jackson适用)

如果用Jackson,可以直接给模型类的Relation字段加注解,绑定专属的序列化和反序列化器:

public class YourModel {
    // 其他字段
    @JsonDeserialize(using = RelationDeserializer.class)
    @JsonSerialize(using = RelationSerializer.class)
    private Relation relation;

    // getter/setter
}

// 反序列化器:处理expand的Map转Relation
public class RelationDeserializer extends JsonDeserializer<Relation> {
    @Override
    public Relation deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node = p.getCodec().readTree(p);
        return new Relation(
            node.get("id").asText(),
            node.get("name").asText()
        );
    }
}

// 序列化器:处理Relation转id字符串
public class RelationSerializer extends JsonSerializer<Relation> {
    @Override
    public void serialize(Relation value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString(value.getId());
    }
}

这种方式直接绑定到字段上,代码更集中,不需要额外的适配类。


内容的提问来源于stack exchange,提问作者TomTom101

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 10:45:34