杰克逊预处理反序列化

时间:2018-10-25 13:57:12

标签: java json jackson

反序列化对象时,我想对json进行一些转换(移动/更改/添加字段),然后继续处理反序列化的对象。这可能吗?

简单示例:

输入JSON

{
    "first": "thing",
    "seconds": [ 55, 67, 12 ]
}

我的对象

public class MyObject {
    private String new;
    private int second;

    // getters and setters
}

反序列化器

public class MyObjectDeserializer extends JsonDeserializer<MyObject> {

    @Override
    public MyObject deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException {
        JsonNode json = p.getCodec().readTree(p);
        JsonNode translatedJson = translate(json);

        // continue processing MyObject like ObjectMapper#readValue would using the translated json
    }

    private JsonNode translate(final JsonNode json) {
        ObjectNode object = (ObjectNode) json;

        // Update 'first' to 'new'
        object.put("new", object.get("first").asText()).remove("first");

        // Find the max in 'seconds' and add it as 'second'
        JsonNode seconds = object.get("seconds");
        int max = 0;
        for (int i = 0; i < seconds.size(); i++) {
            max = Math.max(max, seconds.get(i).asInt());
        }
        object.put("second", max).remove("seconds");

        return object;
    }
}

2 个答案:

答案 0 :(得分:2)

我宁愿注释MyObject而不是实现单独的反序列化器。这是一个示例,允许您将数据从JSON往返传递到Java,然后再次返回。

public static void main(String... args) throws Exception {
    String json = "{\"first\": \"thing\", \"seconds\": [55, 67, 12]}";
    ObjectMapper mapper = new ObjectMapper();
    MyObject mo = mapper.readValue(json, MyObject.class);
    System.out.println(mo);
}

public static class MyObject {
    private final String news;
    private final List<Integer> seconds;
    private final int max;

    @JsonCreator
    public MyObject(@JsonProperty("first") String news,
                    @JsonProperty("seconds") List<Integer> seconds) {
        this.news = news;
        this.seconds = seconds;
        this.max = Collections.max(seconds);
    }

    public String getNew() {
        return news;
    }

    public int getSecond() {
        return max;
    }

    @Override
    public String toString() {
        return "{\"first\": \"" + news + "\", \"seconds\": " + seconds + "}";
    }
}

答案 1 :(得分:1)

是的,您可以使用ObjectCodec中的JsonParser

public class MyObjectDeserializer extends JsonDeserializer<MyObject> {

    @Override
    public MyObject deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException {
        ObjectCodec codec = p.getCodec();
        JsonNode json = coded.readTree(p);
        JsonNode translatedJson = translate(json);

        // continue processing MyObject like ObjectMapper#readValue would using the translated json
        return codec.treeToValue(node, MyObject.class);
    }

    private JsonNode translate(final JsonNode json) {
        ObjectNode object = (ObjectNode) json;

        // Update 'first' to 'new'
        object.put("new", object.get("first").asText()).remove("first");

        // Find the max in 'seconds' and add it as 'second'
        JsonNode seconds = object.get("seconds");
        int max = 0;
        for (int i = 0; i < seconds.size(); i++) {
            max = Math.max(max, seconds.get(i).asInt());
        }
        object.put("second", max).remove("seconds");

        return object;
    }
}

请注意,您不能在Java类中使用new作为字段名,因为它是保留关键字。