Jackson定制解串器打破了其他领域的反序列化 [英] Jackson custom deserializer breaks deserialization of other fields

查看:108
本文介绍了Jackson定制解串器打破了其他领域的反序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将JsonArray反序列化为布尔值.如果数组存在且不为空,则该值应设置为"true". 问题是,我的自定义反序列化器虽然可以正常工作,但是却破坏了其余字段的反序列化-它们被设置为null.

I need to deserialize JsonArray to a boolean value. If an array exists and is not empty the value should be set to "true". The problem is, my custom deserializer, while functional, breaks deserialization of the rest of the fields - they are being set to null.

对象:

private static class TestObject {
    private String name;

    @JsonProperty("arr")
    @JsonDeserialize(using = Deserializer.class)
    private Boolean exists = null;

    private Integer logins;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Boolean getExists() {
        return exists;
    }

    public void setExists(boolean exists) {
        this.exists = exists;
    }

    public Integer getLogins() {
        return logins;
    }

    public void setLogins(Integer logins) {
        this.logins = logins;
    }

    @Override
    public String toString() {
        return "TestObject{" +
                "name='" + name + '\'' +
                ", exists=" + exists +
                ", logins=" + logins +
                '}';
    }
}

反序列化器:

public class Deserializer extends JsonDeserializer<Boolean> {
    @Override
    public Boolean deserialize(JsonParser jp, DeserializationContext ctxt)
        throws IOException {
        if (jp.getCurrentToken() == JsonToken.START_ARRAY) {
            return true;
        }
        return false;
    }
}

测试

@Test
public void test() throws JsonParseException, IOException {
    Boolean result = deserialize();
}

private Boolean deserialize() throws IOException, JsonParseException,
        JsonProcessingException {
    TestObject testObject = mapper.readValue("{\n" +
                    "  \"arr\": [\n" +
                    "     {\"value\": \"New\"}\n" +
                    "  ],\n" +
                    "  \"name\": \"name\",\n" +
                    "  \"logins\": 36" +
                    "}",
                    TestObject.class);

    System.out.println(testObject.toString());

    return testObject.getExists();
}

如果我删除"arr"数组或将其移到Json的底部,一切都很好.如果我将其放在顶部-TestObject{name='null', exists=true, logins=null}.

If i remove the "arr" array or move it to the bottom of the Json, everything's fine. If i leave it at the top - TestObject{name='null', exists=true, logins=null}.

有一个类似的问题( Jackson Custom Deserializer打破了默认问题) ,但遗憾的是答案为零. 由于当我重新排列Json时代码可以正常工作,因此看起来所有字段都没有使用自定义反序列化器,而是Jackson在执行自定义反序列化器时停止了反序列化.

There was a similar question (Jackson Custom Deserializer breaks default ones), but unfortunately it has zero answers. Since the code works properly when i rearrange Json, it doesn't look like custom deserializer is used for all fields, rather Jackson stops deserialization when it executes custom deserializer.

推荐答案

您的反序列化器可能对数组的内容不感兴趣,但仍必须在解析器上推进读取标记.

Your deserializer may not be interested in the contents of the array but must still advance the read mark on the parser.

您可以立即读取arr的值,然后根据集合的大小决定:

You could read the value of arr at once and decide according to the size of the collection:

@Override
public Boolean deserialize(JsonParser jp, DeserializationContext ctxt)
        throws IOException {
    JsonNode node = jp.getCodec().readTree(jp);
    return node.size() != 0;
}

必须确定集合的 size 而不是完全确定集合的 existence ,因为您的字符串化对象包含arr或Deserializer.deserialize()从来没有执行过.在这种情况下,属性exist将为null.因此,表达不存在的唯一可能的语义是一个空集合.

Deciding on the size of the collection and not on the existence of a collection at all is necessary because either your stringified object contains an arr or the Deserializer.deserialize() is never executed. The property exist will be null in this case. So the only possible semantics to express does not exist is an empty collection.

出于好奇,我尝试了第二种更明确的方法来使解析器保持跟踪.对于现实世界而言,使用上述版本绝对是更好的选择.

Just for curiousity I tried a second more explicit way to keep the parser on track. For real world use the above version is definitely preferable.

@Override
public Boolean deserialize(JsonParser jp, DeserializationContext ctxt)
        throws IOException {
    if (jp.currentToken() == JsonToken.START_ARRAY) {
        jp.nextToken();
        int recursionLevel = 1;
        while(recursionLevel > 0) {
            switch (jp.currentToken()) {
                case START_ARRAY:
                    // just in case of nested arrays
                    recursionLevel++;
                    break;
                case END_ARRAY:
                    recursionLevel--;
                    break;
            }
            jp.nextToken();
        }
        return true;
    }
    return false;
}

这篇关于Jackson定制解串器打破了其他领域的反序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆