javajsonormxstreamoxm

How to get XStream to map back to a typed List?


I'm using XStream to map some JSON back into Java objects. I'll be dealing with a JSON string that might look like this:

{
    "widgets":[
    {
        "widget_name": "Kenny",
        "widget_type": "Character"
    },
        "widget_name": "Apple",
        "widget_type": "Fruit"
    }
    ]
}

Update: I believe this JSON could be interpreted as:

This JSON represents an un-named object that contains a widgets object. The widgets object, in turn, contains an array of other un-named objects. Each of these un-named objects contain two properties: widget_name and widget_type.

Each Widget in this widgetlist corresponds to a POJO:

public class Widget {
    private String name;
    private String type;

    // ...etc.
}

I'd like the above JSON string to map back to a List<Widget>, but I can't seem to figure out how to alias the class correctly:

XStream xs = new XStream();
xs.alias("widgetlist", List.class); // Not a List<Widget> !

How can I get the xs mapper to translate widgetlist into a List<Widget>? Thanks in advance.


Solution

  • This piece of code worked for me, however the JSON generated is not similar to the one you have. If you were to use the JsonHierarchicalStreamDriver instead of the JettisonMappedXmlDriver you would get the same JSON as you have in your question. Downside of this is that the JsonHierarchicalStreamDriver cannot read JSON and will give an UnsupportedOperationException if you try.

    XStream xstream = new XStream(new JettisonMappedXmlDriver());
    xstream.setMode(XStream.NO_REFERENCES); 
    xstream.alias("widgetlist", List.class);
    xstream.alias("widget", Widget.class);
    List<Widget> widgetlist = new ArrayList<Widget>();
    Widget w1 = new Widget("Kenny", "Character");
    Widget w2 = new Widget("Apple", "Fruit");
    widgetlist.add(w1);
    widgetlist.add(w2);
    String serialized = xstream.toXML(widgetlist);
    System.out.println(serialized);
    List<Widget> unserialized = (List<Widget>)xstream.fromXML(serialized);
    System.out.println("Size: "+unserialized.size());
    

    The generated XML by JettionMappedXmlDriver

    {
        "widgetlist": {
            "widget": [
                {
                    "name": "Kenny",
                    "type": "Character"
                },
                {
                    "name": "Apple",
                    "type": "Fruit"
                }
            ]
        }
    }
    

    Interpretation

    The JSON is the DROP_ROOT_MODE version of the below JSON(un-named object, if you like). You can therefore look at it as an un-named object that contains a list of Widget. The Widget object still have the same structure as described in the question.

    public class WidgetList {
        List<Widget> widgets;
    
        public WidgetList() {
            this.widgets = new ArrayList<>();
        }
    }
    

    Xstream settings

        xstream.setMode(XStream.NO_REFERENCES);
        xstream.alias("widgets", List.class);
        xstream.addImplicitCollection(WidgetList.class, "widgets");
        xstream.alias("widgets", Widget.class);
        xstream.alias("widgetsL", WidgetList.class);
    

    JSON Output

    {
        "widgetsL": {
            "widgets": [
                {
                    "name": "Kenny",
                    "type": "Character"
                },
                {
                    "name": "Apple",
                    "type": "Fruit"
                }
            ]
        }
    }