首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用Jackson在对象中包含原始JSON?

如何使用Jackson在对象中包含原始JSON?
EN

Stack Overflow用户
提问于 2011-01-24 22:56:18
回答 12查看 99.9K关注 0票数 116

当使用Jackson对对象进行(反)序列化时,我尝试在Java对象中包含原始JSON。为了测试此功能,我编写了以下测试:

代码语言:javascript
复制
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);
}

代码输出以下行:

代码语言:javascript
复制
{"foo":"one","bar":{"A":false}}

JSON正是我想要的样子。不幸的是,当尝试将JSON读回对象时,代码会失败并出现异常。以下是例外情况:

org.codehaus.jackson.map.JsonMappingException:无法反序列化位于Source: java.io.StringReader@d70d7a; line: 1, column: 13的java.lang.String out of START_OBJECT token的实例

为什么Jackson在一个方向上工作得很好,而在另一个方向上却失败了?它似乎应该能够再次将自己的输出作为输入。我知道我正在尝试做的事情是非正统的(一般的建议是为bar创建一个内部对象,该对象具有一个名为A的属性),但是我根本不想与这个JSON交互。我的代码充当这段代码的传递--我想接收这个JSON,并在不接触任何东西的情况下再次将其发送出去,因为当JSON发生变化时,我不希望我的代码需要修改。

谢谢你的建议。

编辑:使Pojo成为一个静态类,这会导致不同的错误。

EN

回答 12

Stack Overflow用户

回答已采纳

发布于 2011-01-25 03:36:10

@JsonRawValue仅用于序列化端,因为反向处理起来有点棘手。实际上,添加它是为了允许注入预编码的内容。

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

但我认为对于您的特定情况,一个变通方法是将type指定为'java.lang.Object',因为这应该可以正常工作:对于序列化,String将按原样输出,而对于反序列化,它将被反序列化为Map。实际上,如果是这样的话,您可能希望有单独的getter/setter;getter将为序列化返回String (并且需要@JsonRawValue);而setter将接受Map或Object。如果有意义,您可以将其重新编码为字符串。

票数 72
EN

Stack Overflow用户

发布于 2012-07-12 21:10:28

@StaxMan answer之后,我做了以下工作,看起来很棒:

代码语言:javascript
复制
public class Pojo {
  Object json;

  @JsonRawValue
  public String getJson() {
    // default raw value: null or "[]"
    return json == null ? null : json.toString();
  }

  public void setJson(JsonNode node) {
    this.json = node;
  }
}

而且,为了忠实于最初的问题,这里是工作测试:

代码语言:javascript
复制
public class PojoTest {
  ObjectMapper mapper = new ObjectMapper();

  @Test
  public void test() throws IOException {
    Pojo pojo = new Pojo("{\"foo\":18}");

    String output = mapper.writeValueAsString(pojo);
    assertThat(output).isEqualTo("{\"json\":{\"foo\":18}}");

    Pojo deserialized = mapper.readValue(output, Pojo.class);
    assertThat(deserialized.json.toString()).isEqualTo("{\"foo\":18}");
    // deserialized.json == {"foo":18}
  }
}
票数 65
EN

Stack Overflow用户

发布于 2014-06-06 23:08:09

我可以使用一个自定义的反序列化程序(从here中剪切和粘贴)来做到这一点。

代码语言:javascript
复制
package etc;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

/**
 * Keeps json value as json, does not try to deserialize it
 * @author roytruelove
 *
 */
public class KeepAsJsonDeserialzier extends JsonDeserializer<String> {

    @Override
    public String deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {

        TreeNode tree = jp.getCodec().readTree(jp);
        return tree.toString();
    }
}
票数 42
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4783421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档