在Jackson的反射反序列化之上进行自定义反序列化

时间:2014-01-31 00:31:44

标签: java json jackson

我想在使用Jackson 1.9反序列化特定类型时运行一些自定义代码。但是,我不想手写整个反序列化器,只需添加默认行为即可。然而,尝试以JsonDeserializer天真的方式执行此操作会导致无限递归。目前,我的方法使用完全独立的ObjectMapper,但这感觉就像一个巨大的黑客。

private static class SpecialDeserializer extends JsonDeserializer<Special> {
    @Override
    public Special deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        JsonNode jsonNode = jp.readValueAsTree();
        ObjectMapper otherMapper = getOtherMapper();
        Special special = otherMapper.readValue(jsonNode, Special.class);
        special.setJsonNode(jsonNode);
        return special;
    }
}

2 个答案:

答案 0 :(得分:2)

Polymorphic deserialization应该能够处理从输入内容中导出输入的类型。如果您需要自定义反序列化,则可以通过注释实现。请参阅this example以供参考。

(不回答实际问题的道歉;这可以回答我从“海报”评论中推断出的“根”问题。

答案 1 :(得分:1)

如果只想为一个类实现此特殊行为,则可以创建具有相同属性集的其他类型。我不确定这是否是您问题的真实答案,但请参阅下面的示例。 POJO类具有属性:

@JsonDeserialize(using = SpecialJsonDeserializer.class)
class Special {

    private String name;

    //getters, setters, toString
}

内部类型的反序列化器:

class SpecialJsonDeserializer extends JsonDeserializer<Special> {
    @Override
    public Special deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
            JsonProcessingException {
        InnerSpecial innerSpecial = jp.readValueAs(InnerSpecial.class);

        return innerSpecial.createRealSpecial();
    }

    private static class InnerSpecial {

        public String name;

        public Special createRealSpecial() {
            Special special = new Special();
            // copy other properties, add additional code
            special.setName(name);

            return special;
        }
    }
}

简单用法:

public class JsonProgram {

    public static void main(String[] args) throws IOException {
        Special special = new Special();
        special.setName("ye");

        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(special);
        System.out.println(json);
        System.out.println(mapper.readValue(json, Special.class));
    }
}

我认为,这比你的黑客少一点,但它仍然是黑客攻击。