当使用Jackson对对象进行(反)序列化时,我尝试在Java对象中包含原始JSON。为了测试此功能,我编写了以下测试:
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读回对象时,代码会失败并出现异常。以下是例外情况:
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成为一个静态类,这会导致不同的错误。
发布于 2011-01-25 03:36:10
@JsonRawValue仅用于序列化端,因为反向处理起来有点棘手。实际上,添加它是为了允许注入预编码的内容。
我猜有可能添加对反向的支持,尽管这将是相当尴尬的:内容将必须被解析,然后重写回“原始”形式,这可能是相同的,也可能不是相同的(因为字符引用可能不同)。这适用于一般情况。但也许它对某些子集的问题是有意义的。
但我认为对于您的特定情况,一个变通方法是将type指定为'java.lang.Object',因为这应该可以正常工作:对于序列化,String将按原样输出,而对于反序列化,它将被反序列化为Map。实际上,如果是这样的话,您可能希望有单独的getter/setter;getter将为序列化返回String (并且需要@JsonRawValue);而setter将接受Map或Object。如果有意义,您可以将其重新编码为字符串。
发布于 2012-07-12 21:10:28
在@StaxMan answer之后,我做了以下工作,看起来很棒:
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;
}
}
而且,为了忠实于最初的问题,这里是工作测试:
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}
}
}
发布于 2014-06-06 23:08:09
我可以使用一个自定义的反序列化程序(从here中剪切和粘贴)来做到这一点。
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();
}
}
https://stackoverflow.com/questions/4783421
复制相似问题