bhi*_*rom 98 java json inner-classes jackson
当使用Jackson(de)序列化对象时,我试图在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);
}
Run Code Online (Sandbox Code Playgroud)
代码输出以下行:
{"foo":"one","bar":{"A":false}}
Run Code Online (Sandbox Code Playgroud)
JSON正是我想要看的东西.不幸的是,在尝试将JSON读回到对象时,代码失败并出现异常.这是一个例外:
org.codehaus.jackson.map.JsonMappingException:无法在[来源:java.io.StringReader@d70d7a;中的START_OBJECT标记中反序列化java.lang.String的实例.line:1,column:13](通过参考链:com.tnal.prism.cobalt.gather.testing.Pojo ["bar"])
为什么杰克逊在一个方向上运作良好但在向另一个方向运转时失败?看起来它应该能够再次将自己的输出作为输入.我知道我正在尝试做的是非正统的(一般的建议是创建一个内部对象,bar其中有一个名为的属性A),但我根本不想与这个JSON交互.我的代码充当了这段代码的传递 - 我想要接受这个JSON并再次发回它而不会触及任何东西,因为当JSON更改时我不希望我的代码需要修改.
感谢您的建议.
编辑:使Pojo成为静态类,导致不同的错误.
Sta*_*Man 57
@JsonRawValue仅用于序列化,因为反向操作有点棘手.实际上,它被添加以允许注入预编码的内容.
我想有可能添加对反向的支持,虽然这很尴尬:内容必须被解析,然后重新写回"原始"形式,这可能是也可能不一样(因为字符引用)可能不同).这是一般情况.但也许这对某些问题是有意义的.
但我认为一个解决您的特定情况下,将指定类型为"java.lang.Object继承",因为这应该可以工作:序列化,字符串将被原样输出,和反序列化,它将被作为反序列化一张地图.实际上你可能想要有单独的getter/setter,如果是这样的话; getter将返回String以进行序列化(并且需要@JsonRawValue); 和setter将采用Map或Object.如果有意义的话,你可以将它重新编码为String.
yve*_*lem 49
在@StaxMan回答之后,我做了以下作品,就像一个魅力:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
并且,为了忠实于最初的问题,这是工作测试:
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}
}
}
Run Code Online (Sandbox Code Playgroud)
Roy*_*ove 33
我可以用自定义解串器要做到这一点(剪切和粘贴来自这里)
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();
}
}
Run Code Online (Sandbox Code Playgroud)
ana*_*gaf 15
@JsonSetter可能有所帮助.查看我的示例('data'应该包含未解析的JSON):
class Purchase
{
String data;
@JsonProperty("signature")
String signature;
@JsonSetter("data")
void setData(JsonNode data)
{
this.data = data.toString();
}
}
Run Code Online (Sandbox Code Playgroud)
这是你的内部类的问题。该类Pojo是测试类的非静态内部类,Jackson 无法实例化该类。所以它可以序列化,但不能反序列化。
像这样重新定义你的类:
public static class Pojo {
public String foo;
@JsonRawValue
public String bar;
}
Run Code Online (Sandbox Code Playgroud)
注意添加static
| 归档时间: |
|
| 查看次数: |
71382 次 |
| 最近记录: |