Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
199 views
in Technique[技术] by (71.8m points)

java - How can I include raw JSON in an object using Jackson?

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);
}

The code outputs the following line:

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

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: 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"])

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.

Thanks for the advice.

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

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

@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.

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...