自定义杰克逊解组行为

时间:2014-06-13 14:45:15

标签: java json jaxb jackson

我使用Jackson fasterxml来解组JSON。在我的对象中有两种属性:输入属性和计算属性。在输入JSON中,我只获得输入值。

计算值实际上取决于输入值。我必须在引用对象之前填充这些值。所以我只是检查杰克逊是否有任何钩子,以便我可以在那里进行计算。例如,JAXB提供afterUnmarshal方法来自定义解组行为:

void afterUnmarshal(Unmarshaller u, Object parent)

但我找不到有关定制杰克逊的类似信息。杰克逊是否提供了任何这样的框架钩子来定制解组行为?

2 个答案:

答案 0 :(得分:5)

我宁愿建议使用constructor creators使模型对象保持不变。也就是说,所有JSON值都传递给构造函数,该构造函数将初始化其他计算属性。

无论如何,如果你想在反序列化后自定义一个对象(不为每个类型编写一个反序列化器),你可以modify the deserializer以最终调用新构造实例的特殊方法的方式{{3}} 。这是一个适用于实现特殊接口的所有类的示例(可以考虑使用注释来标记post构造方法)。

public class JacksonPostConstruct {

    public static interface PostConstructor {
        void postConstruct();
    }

    public static class Bean implements PostConstructor {
        private final String field;

        @JsonCreator
        public Bean(@JsonProperty("field") String field) {
            this.field = field;
        }

        public void postConstruct() {
            System.out.println("Post construct: " + toString());
        }

        @Override
        public String toString() {
            return "Bean{" +
                    "field='" + field + '\'' +
                    '}';
        }
    }

    private static class PostConstructDeserializer extends DelegatingDeserializer {
        private final JsonDeserializer<?> deserializer;

        public PostConstructDeserializer(JsonDeserializer<?> deserializer) {
            super(deserializer);
            this.deserializer = deserializer;
        }

        @Override
        protected JsonDeserializer<?> newDelegatingInstance(JsonDeserializer<?> newDelegatee) {
            return deserializer;
        }

        @Override
        public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
            Object result = _delegatee.deserialize(jp, ctxt);
            if (result instanceof PostConstructor) {
                ((PostConstructor) result).postConstruct();
            }
            return result;
        }
    }

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.setDeserializerModifier(new BeanDeserializerModifier() {
            @Override
            public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
                                                          BeanDescription beanDesc,
                                                          final JsonDeserializer<?> deserializer) {
               return new PostConstructDeserializer(deserializer);
            }
        });
        mapper.registerModule(module);
        String json = "{\"field\":\"value\"}";
        System.out.println(mapper.readValue(json, Bean.class));
    }

}

输出:

Post construct: Bean{field='value'}
Bean{field='value'}

答案 1 :(得分:2)

我们假设您的JSON看起来像这样:

{
    "input1" : "Input value",
    "input2" : 3
}

您的POJO课程如下:

class Entity {

    private String input1;
    private int input2;
    private String calculated1;
    private long calculated2;

    ...
}

在这种情况下,您可以为Entity类编写自定义反序列化程序:

class EntityJsonDeserializer extends JsonDeserializer<Entity> {

    @Override
    public Entity deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
            JsonProcessingException {
        InnerEntity innerEntity = jp.readValueAs(InnerEntity.class);

        Entity entity = new Entity();
        entity.setInput1(innerEntity.input1);
        entity.setInput2(innerEntity.input2);
        entity.recalculate();

        return entity;
    }

    public static class InnerEntity {
        public String input1;
        public int input2;
    }
}

在上面的课程中,您可以看到Entityrecalculate方法。它看起来像这样:

public void recalculate() {
    calculated1 = input1 + input2;
    calculated2 = input1.length() + input2;
}

您也可以将此逻辑移至解串器类。

现在,您必须通知Jackson您要使用自定义反序列化器:

@JsonDeserialize(using = EntityJsonDeserializer.class)
class Entity {
...
}

以下示例显示了如何使用这些类:

ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.readValue(json, Entity.class));

此程序打印:

Entity [input1=Input value, input2=3, calculated1=Input value3, calculated2=14]
相关问题