1

我无法让杰克逊尊重我的自定义 JsonDeserializer。情况是,我有一个类MyClass,其中包含另一个类的列表OtherClass,这是我无法控制的(所以我无法对其进行注释)。此类OtherClass是具有多个实现的接口。我不在乎原件OtherClass是什么,我希望它们始终反序列化为BasicOtherClass.

这是我所拥有的:

@Getter
public class MyClass {

    @JsonProperty("otherclasses")
    @JsonSerialize(contentUsing=OtherClassSerializer.class)
    @JsonDeserialize(contentUsing=OtherClassDeserializer.class)
    private List<OtherClass> otherClasses;

    public MyClass(
            @JsonProperty("otherclasses")
            @JsonDeserialize(contentUsing=OtherClassDeserializer.class)
            List<OtherClass> otherClasses) {
        this.otherClass = otherClass;
    }
}


public static class OtherClassSerializer extends JsonSerializer<OtherClass> {

    @Override
    public void serialize(OtherClass otherClass, JsonGenerator gen, SerializerProvider serializers)
            throws IOException, JsonProcessingException {

        gen.writeStartObject();
        gen.writeStringField("name", otherClass.getName());
        gen.writeStringField("value", otherClass.getValue());
        gen.writeEndObject();
    }

    /** This method is required when default typing is enabled */
    @Override
    public void serializeWithType(
            OtherClass otherClass, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer)
                    throws JsonProcessingException, IOException {

        typeSer.writeTypePrefixForScalar(value, gen, OtherClass.class);
        serialize(value, gen, serializers);
        typeSer.writeTypeSuffixForScalar(value, gen);
    }
}


public static class OtherClassDeserializer extends JsonDeserializer<Header> {

    @Override
    public Header deserialize(JsonParser p, DeserializationContext ctxt) throws IOException,
            JsonProcessingException {

        if (p.getCurrentToken() != JsonToken.START_OBJECT) {
            throw new IllegalStateException("Failed to parse OtherClass from json");
        }

        String name = null;
        String value = null;

        while (p.nextToken() != JsonToken.END_OBJECT) {
            String key = p.getText();
            p.nextToken();
            String val = p.getText();
            if (key.equals("name")) {
                name = val;
            } else if (key.equals("value")) {
                value = val;
            }
        }

        return new BasicOtherClass(name, value);
    }
}

这就是我想要开始工作的:

ObjectMapper mapper = new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
OtherClass otherClass = new BufferedOtherClass("name value");
MyClass myClass = new MyClass(Lists.newArrayList(otherClass));
String json = mapper.writeValueAsString(myClass);

// json == ["com.bschlenk.MyClass", {"otherclass": ["java.util.ArrayList", [["com.other.OtherClass", {"name": "name", "value", "value"}]]]}]

但是当我尝试将该json读回时MyClass,它失败了:

MyClass parsed = mapper.readValue(json, MyClass.class);

// com.fasterxml.jackson.databind.JsonMappingException:
// Can not construct instance of org.apache.http.Header, problem:
// abstract types either need to be mapped to concrete types,
// have custom deserializer,
// or be instantiated with additional type information

这在我没有启用类型信息时有效。MyClass但是,我无法控制其他正在序列化的代码,并且它具有类型信息。

我想要做的甚至可能吗?为什么不mapper.readValue使用我的自定义JsonDeserializer类?这是设计使然吗?

4

0 回答 0