Jackson JSON Processor
  1. Jackson JSON Processor
  2. JACKSON-163

Add ser/deser feature for ObjectMapper to allow "wrapped" output (JAXB compatibility)

    Details

    • Type: Improvement Improvement
    • Status: Closed Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 1.2
    • Fix Version/s: 1.7
    • Component/s: None
    • Labels:
      None
    • Number of attachments :
      0

      Description

      One difference between Jackson output, and xml-to-json conversion induced content is that Jackson does not "wrap" root level object in a dummy object. But when converting from xml, there is an extra level of wrapping which results in such extra wrapping.

      Although Jackson does the right thing from pure JSON perspective, it would make sense to allow a "compatibility mode", in which it would be possible to add single level of wrapping, if necessary name can be introspected, usually using JAXB annotation introspector, and per-class @XmlRootElement annotation.

      (note: this will require some changes to annotation introspector interface; but there are other similar mostly-xml-related enhancements needed)

        Activity

        Hide
        Tatu Saloranta added a comment -

        Ok. I just do not understand what he is trying to get – root element in JSON has no name. But reading through the chain I guess he's probably referring to your work-around, and choice of name? This would then be related to JACKSON-195, but only in sense that without it there would be no way to know intended type (and hence name) of root wrapper.

        Anyway: back to this feature. Access to root name does exist. I forgot exactly why I thought this would not be as easy... will need to investigate after closing 1.5.0 (RSN).

        Show
        Tatu Saloranta added a comment - Ok. I just do not understand what he is trying to get – root element in JSON has no name. But reading through the chain I guess he's probably referring to your work-around, and choice of name? This would then be related to JACKSON-195 , but only in sense that without it there would be no way to know intended type (and hence name) of root wrapper. Anyway: back to this feature. Access to root name does exist. I forgot exactly why I thought this would not be as easy... will need to investigate after closing 1.5.0 (RSN).
        Hide
        Samuel Cook added a comment -

        Hi,

        Sorry for not checking back on this ticket earlier.

        Apologies also if I was not clear in my earlier comment - I'll try to provide some further detail now.

        Take for example the following PersonBean class.

        @XmlRootElement(name="person")
        public class PersonBean
        {
        	private String name = "foo";
        	private int age = 9;
        	
        	// getters and setters omitted for brevity
        }
        

        When marshalling this to XML using JAXB, the @XmlRootElement(name) parameter is honoured, and the XML produced is as follows:

        <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
        <person>
        	<age>9</age>
        	<name>foo</name>
        </person>
        

        However, when using Jackson to marshal the same bean into JSON, the following output is produced:

        {"personBean":{"name":"foo","age":9}}
        

        Here the class name, "personBean" is used as the root element, despite the @XmlRootElement(name="person") annotation.

        I'm not sure if this is related to this issue or JACKSON-195, but essentially my vote was for enhancing Jackson to honour the @XmlRootElement(name) property when marshalling objects to JSON.

        Your point that the root element in JSON has no name is interesting. It's a valid point; there's no real necessity to have the "personBean" node at all - name and age could be top-level elements. I wonder if this is a side-effect of using Spring's MappingJacksonJsonView class, and nothing to do with Jackson at all...

        Show
        Samuel Cook added a comment - Hi, Sorry for not checking back on this ticket earlier. Apologies also if I was not clear in my earlier comment - I'll try to provide some further detail now. Take for example the following PersonBean class. @XmlRootElement(name= "person" ) public class PersonBean { private String name = "foo" ; private int age = 9; // getters and setters omitted for brevity } When marshalling this to XML using JAXB, the @XmlRootElement(name) parameter is honoured, and the XML produced is as follows: <?xml version= "1.0" encoding= "UTF-8" standalone= "yes" ?> <person> <age> 9 </age> <name> foo </name> </person> However, when using Jackson to marshal the same bean into JSON, the following output is produced: { "personBean" :{ "name" : "foo" , "age" :9}} Here the class name, "personBean" is used as the root element, despite the @XmlRootElement(name="person") annotation. I'm not sure if this is related to this issue or JACKSON-195 , but essentially my vote was for enhancing Jackson to honour the @XmlRootElement(name) property when marshalling objects to JSON. Your point that the root element in JSON has no name is interesting. It's a valid point; there's no real necessity to have the "personBean" node at all - name and age could be top-level elements. I wonder if this is a side-effect of using Spring's MappingJacksonJsonView class, and nothing to do with Jackson at all...
        Hide
        Tatu Saloranta added a comment -

        Hi Samuel. This really depends on whether this is at root level, or via reference.
        If root level, yes, it must be something outside of Jackson. Also: some other json-producing libs (like Jettison that many JAX-RS impls default to, in absence of explicit configuration) do use wrapping like this.
        It is quite possible Spring's wrapper could add additional wrapping as well, perhaps to allow for reliable auto-detection of intended type.

        "personBean" would be added only if instance was reference through property of another bean (not at root level). But it sounds like this is not what you are doing here.

        Show
        Tatu Saloranta added a comment - Hi Samuel. This really depends on whether this is at root level, or via reference. If root level, yes, it must be something outside of Jackson. Also: some other json-producing libs (like Jettison that many JAX-RS impls default to, in absence of explicit configuration) do use wrapping like this. It is quite possible Spring's wrapper could add additional wrapping as well, perhaps to allow for reliable auto-detection of intended type. "personBean" would be added only if instance was reference through property of another bean (not at root level). But it sounds like this is not what you are doing here.
        Hide
        Samuel Cook added a comment -

        Hi,

        Hopefully I'm not dragging this ticket too off-track here.

        I've done some digging into the way that Spring's MappingJacksonJsonView class works. It seems to put the to-be-marshalled POJO instance into a map, with a key of the name of the class (in this case, "personBean"). This key is always the name of the class, regardless of the @XmlRootElement(name) value. It then passes the map as the value to ObjectMapper's writeValue(JsonGenerator, Object) method, which appears to render the key as the root element name.

        So it does sound like the behaviour I'm seeing is a result of Spring trying to be clever about wrapping nodes - as you say, it may be required for auto-detection when the JSON comes back to the Java side.

        Sorry if this whole thing has been a bit distracting!

        Cheers,

        Sam

        Show
        Samuel Cook added a comment - Hi, Hopefully I'm not dragging this ticket too off-track here. I've done some digging into the way that Spring's MappingJacksonJsonView class works. It seems to put the to-be-marshalled POJO instance into a map, with a key of the name of the class (in this case, "personBean" ). This key is always the name of the class, regardless of the @XmlRootElement(name) value. It then passes the map as the value to ObjectMapper 's writeValue(JsonGenerator, Object) method, which appears to render the key as the root element name. So it does sound like the behaviour I'm seeing is a result of Spring trying to be clever about wrapping nodes - as you say, it may be required for auto-detection when the JSON comes back to the Java side. Sorry if this whole thing has been a bit distracting! Cheers, Sam
        Hide
        Tatu Saloranta added a comment -

        Implemented serialization side support, so that wrapping can be enabled easily by setting 'SerializationConfig.Feature.WRAP_ROOT_VALUE' to true. If so, extra single-property JSON Object is added; root name comes from value class or forced static type by default, but JAXB annotation introspector adds @XmlRootElement based override as necessary.

        Show
        Tatu Saloranta added a comment - Implemented serialization side support, so that wrapping can be enabled easily by setting 'SerializationConfig.Feature.WRAP_ROOT_VALUE' to true. If so, extra single-property JSON Object is added; root name comes from value class or forced static type by default, but JAXB annotation introspector adds @XmlRootElement based override as necessary.

          People

          • Assignee:
            Tatu Saloranta
            Reporter:
            Tatu Saloranta
          • Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: