Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XStream parse JSON with no root node

Tags:

java

json

xstream

I am currently deserializing JSON using XStream, and it has been working great. However, when I have JSON string like the following

{
    key1: { an_object: { something: 'foobar' } },
    key2: { another_object: { data: 'hi' }
}

most notably it doesn't have a root node, I'm not sure how to parse it. Basically, I want the opposite of DROP_ROOT_NODE for the deserialization.

like image 514
Josh Braegger Avatar asked Aug 11 '09 22:08

Josh Braegger


People also ask

Does JSON require a root element?

Root element JSON may not start with a root element. JSON supports datatype including integer and strings, JSON also supports array. XML does not provide any data type so needs to be parsed into particular datatype.

What is a root element in JSON?

According to the modified Backus-Naur-Form on the right side pane of http://json.org/ the root element of a JSON data structure can be any of these seven types/values: Object Array String Number true false null.

Can JSON have multiple root elements?

Virtual root element:If the incoming JSON document has multiple root elements, enter a virtual root element to be added to the output XML document. This is required because multiple root elements are not valid in XML. Otherwise, the XML parser will fail.


3 Answers

The short answer is "you can't".

XStream needs to know what class to instantiate, it gets that knowledge from JSON (or XML) data. Class name can be aliased, but it can not be omitted. You can work around by:

  1. Manually wrapping your JSON string with root node containing your class name (or alias)
  2. Writing your own reader that would do it for you. However, in this case you'll still need to pass your class name (alias) to that reader either explicitly or by convention (e.g. always prepend 'root' but then configure it as alias to your class in XStream instance) - so I don't think this is any cleaner than #1.
like image 198
ChssPly76 Avatar answered Oct 22 '22 00:10

ChssPly76


I know this is an old question, but I'll post my solution after a whole morning googling. The answer is to provide dummy root node (start and termination tags). In order to accomplish this, one of your best friends is SequenceInputStream:

My code is the following:

        reader = new XppDriver().createReader(new SequenceInputStream(
        Collections.enumeration(Arrays.asList(
        new InputStream[] {
                new ByteArrayInputStream("<PlatformAuditEvents>".getBytes()),
                new FileInputStream(file),
                new ByteArrayInputStream("</PlatformAuditEvents>".getBytes())
            }))
    ));
    in = xstream.createObjectInputStream(reader);

Here I've mixed three InputStream objects, being the first and third ones those providing the required tags missing in the file processed.

This solution was inspired by this SO Question. Hope this helps someone.

like image 34
Juan Carlos González Avatar answered Oct 22 '22 02:10

Juan Carlos González


Use the below code:

XStream xstream = new XStream(new JsonHierarchicalStreamDriver() {
    public HierarchicalStreamWriter createWriter(Writer writer) {
        return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
    } });
like image 38
jayavardhan Avatar answered Oct 22 '22 01:10

jayavardhan