Search code examples
xml-serializationxstream

XStream different alias for same class (Map.class) for different fields


I am using XStream to convert a Java class which has fields of the type java.util.Map. I have a converter for java.util.Map which displays the key of the Map as an xml element and the value of the map as the value for the xml element. I have registered the converter using registerConverter method. When I perform the marshalling, I get the following output.

<cart account_id="123" shift_id="456" account_postings_id="641">
  <supervisor_id>555</supervisor_id>
  <payments>
    <map sequence="1">
      <amount>123.45</amount>
      <billing_method>12345</billing_method>
      <form>card</form>
      <delivery_mode>Q</delivery_mode>
    </map>
    <map sequence="2">
      <amount>123.45</amount>
      <person_id>2333</person_id>
      <form>cash</form>
      <delivery_mode>Q</delivery_mode>
     </map>
  </payments>
  <items>
    <map sequence="3">
      <amount>1.00</amount>
      <type>pay_toll</type>
      <toll_id>1234</toll_id>
    </map>
  </items>
</cart>

Instead of the map tags appearing, I would want to use different tags based on the field name in the class. For example, the Payments list will have tag name payment and the Items list will have a tag name item for each Map element.

How do we dynamically set alias based on field in the same class?

-Anand


Solution

  • I used XStream to create atom feed reports. Entries in the contents can be of different object classes and I wanted to use the class name dynamically. Here is my solution. I created a ObjectContentConverter and passed the XStream on, and then use xstream.aliasField() with getClass().getSimpleName().

    private class ObjectContentConverter implements Converter {
        XStream xStream;
    
        private ObjectContentConverter(XStream xStream) {
            this.xStream = xStream;
        }
    
        @Override
        public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
            String className = WordUtils.uncapitalize(source.getClass().getSimpleName());
            xStream.aliasField(className, Content.class, "objectContent");
            xStream.marshal(source, writer);
        }
    
        @Override
        public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
            return null;  //To change body of implemented methods use File | Settings | File Templates.
        }
    
        @Override
        public boolean canConvert(Class type) {
            return true;  //To change body of implemented methods use File | Settings | File Templates.
        }
    }
    
    xStream.registerLocalConverter(Content.class, "objectContent", new ObjectContentConverter(xStream));