Question

I need to convert Java Object to JSON String. Here is the code that I use for example:

public class XstreamTest {

    public static void main(String[] args) throws Exception {
        Order order = new Order();
        order.id = 1;
        order.products = new ArrayList<Product>();

        Product prod1 = new Product();
        prod1.barCode = "4821111111111";
        Product prod2 = new Product();
        prod2.barCode = "4821111111112";

        order.products.add(prod1);
        order.products.add(prod2);

        System.out.println(toJson(order));

    }

    public static String toJson(Object document) throws Exception {
        XStream xstream = new XStream(new JettisonMappedXmlDriver() {
            public HierarchicalStreamWriter createWriter(Writer writer) {
                return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
            }
        });
        xstream.autodetectAnnotations(true);
        xstream.setMode(XStream.NO_REFERENCES);
        xstream.alias(document.getClass().getSimpleName(),
                document.getClass());
        return xstream.toXML(document);
    }

}

@XStreamAlias("ORDER")
class Order {
    @XStreamAlias("NUMBER")
    public int id;

    @XStreamAlias("PRODUCT")
    @XStreamImplicit(itemFieldName="PRODUCT")
    public List<Product> products;
}

class Product {
    @XStreamAlias("BARCODE")
    public String barCode;
}

After running, I have result:

{
  "NUMBER": 1,
  "PRODUCT": {
    "BARCODE": "4821111111111"
  },
  "PRODUCT": {
    "BARCODE": "4821111111112"
  }
}

I check json on http://www.jslint.com/ and get error: Duplicate 'PRODUCT'.

Please help! What I do wrong? Or may be it bug in XStream?

Was it helpful?

Solution

Just remove the annotation @XStreamImplicit(itemFieldName="PRODUCT") from your products field in Order class. This instructs XStream to serialize your collection as an implicit collection, which means there will be no root object for the collection and all of its elements will be serialized separately and enclosed in an object called with the name of its collection (PRODUCT). This results in a JSON object which has multiple properties with the same name (PRODUCT), which is invalid.

By the way, XStream is originally meant to be serializing XMLs, you might try to use a dedicated JSON serializer library, GSON for instance.

UPDATE

As you are using the same POJOs to deserialize an XML, and removing the mentioned annotation breaks the XML deserialization, you have to configure XStream "manually" so that it can handle the implicit collection during deserialization of the XML:

xstream.addImplicitCollection(Order.class, "products", "PRODUCT", Product.class);

This has the same effect as the annotation except that it applies only to the deserialization.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top