Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moxy: List of objects XML and JSON can't get both look good

I have a problem getting Moxy to generate "good" XML and JSON for a list of inherited objects. Either of the XML looks find or the JSON looks fine, but not at the same time. Here is the model:

public static abstract class Animal {
    private String name;

    protected Animal() {
    }
    protected Animal(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
@XmlRootElement
public static class Tiger extends Animal {
    public Tiger() {
    }
    public Tiger(String name) {
        super(name);
    }
}

@XmlRootElement
public static class Lion extends Animal {
    public Lion() {
    }
    public Lion(String name) {
        super(name);
    }
}

@XmlRootElement
public static class Zoo {
    private List<Animal> animals = new ArrayList<>();

    @XmlElementRef
    public List<Animal> getAnimals() {
        return animals;
    }
    public void setAnimals(List<Animal> animals) {
        this.animals = animals;
    }
    public void addAnimal(Animal a) {
        animals.add(a);
    }
}

The XML and JSON generated from the following Zoo instance

    zoo = new Zoo();
    zoo.addAnimal(new Tiger("Hobbes"));
    zoo.addAnimal(new Lion("Simba"));
    zoo.addAnimal(new Tiger("Sherikan"));

Look like:

  <?xml version="1.0" encoding="UTF-8"?>
  <zoo>
     <tiger>
        <name>Hobbes</name>
     </tiger>
     <lion>
        <name>Simba</name>
     </lion>
     <tiger>
        <name>Sherikan</name>
     </tiger>
  </zoo>
  {
     "zoo" : {
        "tiger" : [ {
           "name" : "Hobbes"
        }, {
           "name" : "Sherikan"
        } ],
        "lion" : [ {
           "name" : "Simba"
        } ]
     }
  }

The XML looks exactly what I want it too, but the JSON is weird. The way that the Moxy uses the type as key does not preserve order among the elements in the list. Is this a bug or feature?

If I change the annotation on Zoo.animals to @XmlElement the JSON output looks fine, but the XML output has changed to something that I can't use.

  {
     "zoo" : {
        "animals" : [ {
           "type" : "tiger",
           "name" : "Hobbes"
        }, {
           "type" : "lion",
           "name" : "Simba"
        }, {
           "type" : "tiger",
           "name" : "Sherikan"
        } ]
     }
  }
  <?xml version="1.0" encoding="UTF-8"?>
  <zoo>
     <animals xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="tiger">
        <name>Hobbes</name>
     </animals>
     <animals xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="lion">
        <name>Simba</name>
     </animals>
     <animals xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="tiger">
        <name>Sherikan</name>
     </animals>
  </zoo>

The only way I've come up with to solve this is to create an external OXM binding file to override the annotation on Zoo.animals. The binding below is registered using the property of JAXBContextProperties.OXM_METADATA_SOURCE.

  <?xml version="1.0"?>
  <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xml-accessor-type="PUBLIC_MEMBER" xml-accessor-order="ALPHABETICAL"
                xml-mapping-metadata-complete="false"
                package-name="com.example">
     <java-types>
        <java-type name="com.example.JAXBTest2$Zoo">
           <java-attributes>
              <xml-element java-attribute="animals"/>
           </java-attributes>
        </java-type>
     </java-types>
  </xml-bindings>

Is there a better solution to this that doesn't use an external binding file?

like image 315
user3099799 Avatar asked Nov 02 '22 09:11

user3099799


1 Answers

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group

The way that the Moxy uses the type as key does not preserve order among the elements in the list. Is this a bug or feature?

We did that on purpose to prevent the key from being repeated.

The only way I've come up with to solve this is to create an external OXM binding file to override the annotation on Zoo.animals. The binding below is registered using the property of JAXBContextProperties.OXM_METADATA_SOURCE.

This is how I would recommend solving your use case.

like image 143
bdoughan Avatar answered Nov 08 '22 05:11

bdoughan