【问题标题】:Unable to Deserialize Using JsonParser in Jackson无法在 Jackson 中使用 JsonParser 反序列化
【发布时间】:2012-08-05 17:10:12
【问题描述】:

我正在尝试使用org.codehaus.jackson.map.deser.std.StdDeserializer 执行自定义反序列化。

我的主要目标是能够连接到 Jetty 的 JSON 处理结构并使用 Jackson 而不是默认的 JettyJSON。

所以现在,我正在测试这是否可行。

我有一个测试尝试读取一个简单的 JSON 字符串并将其转换为 Presence 对象。

public void testBasicJson() throws JsonParseException,
        JsonMappingException,
        IOException {
    ObjectMapper mapper = new ObjectMapper();
    JsonObjectDeserializer jod = new JsonObjectDeserializer();
    SimpleModule module = new SimpleModule("JsonObjectDeserializer",
        new Version(1, 0, 0, null));
    module.addDeserializer(JsonObject.class, jod);
    mapper.registerModule(module);

    //formatted for easy reading
    String jsonSimple = "{
        \"userEmail\":\"user1@lab.com\",
        \"type\":\"presence\",
        \"domain\":\"lab.com\"
    }";
    JsonObject pres = mapper.readValue(jsonSimple, JsonObject.class);
    System.out.println(pres.toString());
}

Presence 类是:

public class Presence extends JsonObject {
    private static final long serialVersionUID    = 1L;
    protected String userEmail;
    protected String domain;
    protected String type;

    public Presence() {
    }

    //necessary GETTERs and SETTERs are created for userEmail, domain and type

    public String toString() {
        StringBuffer sb = new StringBuffer("\tuser: ");
        sb.append(userEmail);
        sb.append(" - ");
        sb.append(domain);
        return sb.toString();
    }
}

父类是:

import org.cometd.server.ServerMessageImpl;

public abstract class JsonObject extends ServerMessageImpl {
    private static final long   serialVersionUID    = 1L;
}

自定义反序列化器是:

import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.deser.std.StdDeserializer;

public class JsonObjectDeserializer extends StdDeserializer<JsonObject> {
    public JsonObjectDeserializer() {
        super(JsonObject.class);
    }

    @Override
    public JsonObject deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        //so I'm at a loss at this point
        //if (jp.nextToken() != JsonToken.START_OBJECT) {
        //    throw new IOException("Invalid");
        //}
    }
}

我面临的问题是反序列化器的部分。尝试使用 JsonParser 读取令牌不起作用,因为它总是返回 null。

我坚信我非常接近解决方案,并且在反序列化器中只缺少一件事。我只需要一些指导来达到最终目标。

感谢任何帮助!

【问题讨论】:

  • 很高兴您能弄明白!然而有一个问题——类看起来像一个 POJO,ObjectMapper.readValue(...) 应该能够立即阅读它。所以我很好奇为什么需要自定义反序列化器?还是只是为了在需要的情况下学习如何去做? (我确定存在)
  • @StaxMan 是的,您说得对,readValue() 方法应该立即起作用。我需要它做的是能够根据 JSON 字符串中某些字段的存在/不存在返回不同的类对象(不同的父系)。这是我尝试覆盖 Jetty 中默认的 JSON 读取行为。我现在意识到这不是正确的做法。但至少我得了解更多关于杰克逊的知识! :)

标签: java json jetty jackson deserialization


【解决方案1】:

好的,经过几天的探索和发布我的问题仅仅几个小时后,我得到了自己问题的答案。

这是正确推进 JsonParser 的问题。

方法的内容应该是:

public JsonObject deserialize(JsonParser jp, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {
    if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
        throw new IOException("invalid start marker");
    }
    Presence p = new Presence();
    while (jp.nextToken() != JsonToken.END_OBJECT) {
        String fieldname = jp.getCurrentName();
        jp.nextToken();  //move to next token in string
        if ("userEmail".equals(fieldname)) {
            p.setUserEmail(jp.getText());
        } else if ("domain".equals(fieldname)) {
            p.setDomain(jp.getText());
        } else if ("type".equals(fieldname)) {
            p.setType(jp.getText());
        }
    }
    jp.close();
    return p;
}

更清楚地阅读了http://www.cowtowncoder.com/blog/archives/2009/01/entry_132.html 和 Jackson 的 Javadocs 以确定正确的做法。

【讨论】:

    猜你喜欢
    • 2016-04-25
    • 1970-01-01
    • 2015-10-02
    • 2018-12-16
    • 1970-01-01
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 2013-01-08
    相关资源
    最近更新 更多