Problems deserializing JSON for a class using XmlValue and XmlAttribute

已查看 2,472 次
跳至第一个未读帖子

Pål Skjager Løberg

未读,
2014年7月30日 08:21:272014/7/30
收件人 jackso...@googlegroups.com
I have a class with two fields that I need to serialize into both XML and JSON. For XML I'd prefer a format like

<foo key="bar">42.42</foo>

and for JSON it is being serialized as (here I'm open to making changes)

{"key":"bar","value":42.42}


The class looks like this:
@XmlRootElement(name = "foo")
public class Foo {

    @XmlAttribute(name = "key")
    String key;

    @XmlValue
    double value;

    public Foo() {
    }

    public Foo(String key, double value) {
        this.key = key;
        this.value = value;
    }

    // hashCode and equals, getters and setters removed from sample
}



Serializing and deserializing to and from XML works fine using the XMLMapper:

 XmlMapper om = new XmlMapper();
 om.registerModule(new JaxbAnnotationModule());
 om.registerModule(new JacksonXmlModule());

 Foo foo = new Foo("bar", 42.42);

 String xml = om.writeValueAsString(foo);
 assertThat(xml).isXmlEqualTo("<foo key=\"bar\">42.42</foo>");

 Foo parsed = om.readValue(xml, Foo.class);
 assertThat(parsed).isEqualTo(foo);


Serializing to JSON also works fine, but deserializing it is failing with an exception:
 ObjectMapper om = new ObjectMapper();
 om.registerModule(new JaxbAnnotationModule());
 om.registerModule(new JacksonXmlModule());

 Foo foo = new Foo("bar", 42.42);

 String json = om.writeValueAsString(foo);
 assertThat(json).isEqualTo("{\"key\":\"bar\",\"value\":42.42}");

 // The next line throws and exception
 Foo parsed = om.readValue(json, Foo.class);



com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "value" (class com.test.Foo), not marked as ignorable (2 known properties: "", "key"])
 at [Source: {"key":"bar","value":42.42}; line: 1, column: 27] (through reference chain: com.test.Foo["value"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:51)
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:731)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:915)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1292)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1270)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:247)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:118)
at com.fasterxml.jackson.dataformat.xml.deser.XmlTextDeserializer.deserialize(XmlTextDeserializer.java:96)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3051)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2146)


I have looked at the annotations documentation and various discussions, incuding using a @JsonCreator (which breaks the XML side), but have so far not found a solution to to deserializing the JSON. I'm using Jackson 2.4.1 with Jersey 2.10. 

If anyone have suggestions on how to make this work I'd appreciate input.

Tatu Saloranta

未读,
2014年7月30日 19:27:022014/7/30
收件人 jackso...@googlegroups.com
I think the problem is with register JacksonXmlModule for JSON use case: you only need JAXB annotations module, but xml module will try to do its magic, which will confuse a few things in JSON handling (including removing name of property marked with @XmlValue)

So try removing that registration and things should work better.

Hope this helps,

-+ Tatu +-



--
You received this message because you are subscribed to the Google Groups "jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jackson-user...@googlegroups.com.
To post to this group, send email to jackso...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Pål Skjager Løberg

未读,
2014年7月31日 09:49:052014/7/31
收件人 jackso...@googlegroups.com
Thanks. That seems to have done the trick. Not sure why the JacksonXmlModule was registered in the first place, it has just "always" been in there :-/

 -- Paul

Tatu Saloranta

未读,
2014年7月31日 13:16:432014/7/31
收件人 jackso...@googlegroups.com
Yeah that happens, perhaps cut'n paste?

Good to hear it works now, and for both XML and JSON.

-+ Tatu +-

Pål Skjager Løberg

未读,
2014年8月8日 09:16:172014/8/8
收件人 jackso...@googlegroups.com
A somewhat related question,

when I use @XmlValue to annotate a field and then serialize the object as JSON the property is always named "value". Is it possible to change the name of that property to something else using an annotation?

Thanks,

 -- Paul

Tatu Saloranta

未读,
2014年8月9日 14:16:402014/8/9
收件人 jackso...@googlegroups.com
I would expect @JsonProperty to still work; or, if not, @JsonGetter.
If this is not the case, it might ba flaw -- I'd have to check, since combining aspects from multiple annotations is sometimes tricky.

Then again, perhaps @XmlValue should not have effect on naming in JSON (or, anything non-XML).

-+ Tatu +-

Pål Skjager Løberg

未读,
2014年8月9日 15:12:142014/8/9
收件人 jackso...@googlegroups.com

Again it could be me confusing it here by registering the JaxbAnnotationModule() to the ObjectMapper. With that present annotating with @JsonProperty has no effect and @JsonGetter cause an exception.

If I remove JaxbAnnotationModule I get it working, but no longer have any effect of annotations like @XmlElement to name field, but I can get around that by adding @JsonProperty annotations. However, I also use @XmlJavaTypeAdapter to use custom type mappers for some fields and I can not find an equivalent annotation for JSON. If there is a way of doing that I can probably do without the JaxbAnnotationModule and get both JSON and XML working well.

Thanks,

 -- Paul

Tatu Saloranta

未读,
2014年8月9日 16:31:112014/8/9
收件人 jackso...@googlegroups.com
It should be perfectly fine to use JAXB annotations module with JSON; this is done by many to port over JAXB-based serializers to do JSON.

So this sounds like a flaw, most likely in JAXB-annotations module.
I will file a bug and see what can be done to resolve the problem.

In the meantime, I am not sure what the work-around would be, except perhaps custom sub-type of JacksonAnnotationIntrospector which adds support for JAXB annotations you need. That's ugly, but could work.

-+ Tatu +-



Tatu Saloranta

未读,
2014年8月9日 23:02:322014/8/9
收件人 jackso...@googlegroups.com
Ok, issue is:

https://github.com/FasterXML/jackson-module-jaxb-annotations/issues/30

and I managed to find a fix for 2.4.2 so that @JsonProperty override will work.

For 2.5 it should also be possible to configure JaxbAnnotationIntrospector and specify what name should be used as implicit name, or, if specified as null, that no name change should occur at all. While doing that as default may make sense it seems safer to leave default behavior as is.

-+ Tatu +-

Pål Skjager Løberg

未读,
2014年8月12日 03:40:282014/8/12
收件人 jackso...@googlegroups.com

Thanks! I'll give the snapshot go. Is there a planned release of 2.4.2, btw?

 -- Paul

Tatu Saloranta

未读,
2014年8月12日 11:05:062014/8/12
收件人 jackso...@googlegroups.com
We still operate on "released when it's done" system, so there are usually no pre-defined timelines. But on practical level, 2.4.2 will be released in August for sure, and I hope to cut release either this weekend, or next week.
There are enough fixes to justify a patch release at this point, it's just matter of finding time to do it. Another thing to work on afterwards would be to figure out ways to streamline release process: perhaps git sub-projects could help (something mr. Currie was tinkering with).

-+ Tatu +-



回复全部
回复作者
转发
0 个新帖子