如何使用Jackson在对象中包含原始JSON? [英] How can I include raw JSON in an object using Jackson?

查看:185
本文介绍了如何使用Jackson在对象中包含原始JSON?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当使用Jackson(de)序列化对象时,我试图在Java对象中包含原始JSON。为了测试这个功能,我编写了以下测试:

I am trying to include raw JSON inside a Java object when the object is (de)serialized using Jackson. In order to test this functionality, I wrote the following test:

public static class Pojo {
    public String foo;

    @JsonRawValue
    public String bar;
}

@Test
public void test() throws JsonGenerationException, JsonMappingException, IOException {

    String foo = "one";
    String bar = "{\"A\":false}";

    Pojo pojo = new Pojo();
    pojo.foo = foo;
    pojo.bar = bar;

    String json = "{\"foo\":\"" + foo + "\",\"bar\":" + bar + "}";

    ObjectMapper objectMapper = new ObjectMapper();
    String output = objectMapper.writeValueAsString(pojo);
    System.out.println(output);
    assertEquals(json, output);

    Pojo deserialized = objectMapper.readValue(output, Pojo.class);
    assertEquals(foo, deserialized.foo);
    assertEquals(bar, deserialized.bar);
}

代码输出以下行:

{"foo":"one","bar":{"A":false}}

JSON正是我想要看的东西。不幸的是,当尝试将JSON读回到对象时,代码失败并出现异常。以下是例外:

The JSON is exactly how I want things to look. Unfortunately, the code fails with an exception when attempting to read the JSON back in to the object. Here is the exception:


org.codehaus.jackson.map.JsonMappingException:无法从START_OBJECT中反序列化java.lang.String的实例令牌
at [来源:java.io.StringReader@d70d7a; line:1,column:13](通过引用链:com.tnal.prism.cobalt.gather.testing.Pojo [bar])

org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token at [Source: java.io.StringReader@d70d7a; line: 1, column: 13] (through reference chain: com.tnal.prism.cobalt.gather.testing.Pojo["bar"])

为什么杰克逊在一个方向上运作良好但在向另一个方向运转时失败?看起来它应该能够再次将自己的输出作为输入。我知道我要做的是非正统的(一般的建议是为 bar 创建一个内部对象,它有一个名为 A的属性),但我根本不想与这个JSON交互。我的代码充当了这段代码的传递 - 我想接受这个JSON并再次发送它而不会触及任何东西,因为当JSON更改时我不希望我的代码需要修改。

Why does Jackson function just fine in one direction but fail when going the other direction? It seems like it should be able to take its own output as input again. I know what I'm trying to do is unorthodox (the general advice is to create an inner object for bar that has a property named A), but I don't want to interact with this JSON at all. My code is acting as a pass-through for this code -- I want to take in this JSON and send it back out again without touching a thing, because when the JSON changes I don't want my code to need modifications.

感谢您的建议。

编辑:使Pojo成为静态类,导致了不同的错误。

Made Pojo a static class, which was causing a different error.

推荐答案

@JsonRawValue仅用于序列化,因为反向操作有点棘手。实际上它被添加以允许注入预编码的内容。

@JsonRawValue is intended for serialization-side only, since the reverse direction is a bit trickier to handle. In effect it was added to allow injecting pre-encoded content.

我想可以添加对反向的支持,尽管这会很尴尬:内容会有要解析,然后重新写回原始形式,这可能是也可能不相同(因为字符引用可能不同)。
这是一般情况。但也许它对于某些问题子集是有意义的。

I guess it would be possible to add support for reverse, although that would be quite awkward: content will have to be parsed, and then re-written back to "raw" form, which may or may not be the same (since character quoting may differ). This for general case. But perhaps it would make sense for some subset of problems.

但我认为针对您的具体情况的解决办法是将类型指定为'java.lang.Object ',因为这应该可以正常工作:对于序列化,String将按原样输出,而对于反序列化,它将被反序列化为Map。实际上你可能想要有单独的getter / setter,如果是这样的话; getter会返回String进行序列化(需要@JsonRawValue);和setter将采用Map或Object。如果有意义的话,你可以将它重新编码为String。

But I think a work-around for your specific case would be to specify type as 'java.lang.Object', since this should work ok: for serialization, String will be output as is, and for deserialization, it will be deserialized as a Map. Actually you might want to have separate getter/setter if so; getter would return String for serialization (and needs @JsonRawValue); and setter would take either Map or Object. You could re-encode it to a String if that makes sense.

这篇关于如何使用Jackson在对象中包含原始JSON?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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