【问题标题】:Jackson preprocess deserializationJackson 预处理反序列化
【发布时间】:2018-10-25 13:57:12
【问题描述】:

当我反序列化一个对象时,我想对 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;
    }
}

【问题讨论】:

  • 你介意举个例子吗?
  • 除非您可以更改反序列化器本身的代码,否则您必须将其反序列化为对象,然后使用常规代码将其转换为不同的对象结构。
  • 我可以更改反序列化器,但不确定最好的方法,请参见上面的示例。
  • 我不知道你需要这个做什么。我认为将其反序列化为接口类,然后映射到您的域实体是更简洁的设计。此外,new 不是有效的类成员名称。

标签: java json jackson


【解决方案1】:

是的,您可以使用JsonParser 中的ObjectCodec 执行此操作:

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 作为字段名,因为它是保留关键字。

【讨论】:

  • 我将@JsonDeserilize 放在MyObject 的getter/setter 所在的对象声明上,它就像一个魅力。谢谢!
  • @frant.hartm :请修复您的代码 sn-p,而不是“node”,它应该是“translatedJson”。谢谢你的回答,对我帮助很大!
  • 我在这里遗漏了一些东西。您如何在与您的反序列化器相同的类上调用 codec.treeToValue() 。 @JsonDeserializer(使用 = MyObjectDeserializer.class)。 MyObjectDeserializer:: deserialize 被调用,然后当你调用 codec.treeToValue(node, MyObject.class) 不只是再次调用相同的反序列化器进行无限循环吗?
【解决方案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 + "}";
    }
}

【讨论】:

  • 我确实喜欢这种方法,但我的实际用例有点复杂,比如从对象中找到最大值。
猜你喜欢
  • 2012-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-29
  • 1970-01-01
  • 2014-07-15
  • 2023-04-02
  • 1970-01-01
相关资源
最近更新 更多