views:

1024

answers:

2

Hi,

In short, this is a sketch of the JSON object I want to parse in JAVA:

{
    object1: {
            item1: //[String | Array | Object] ,
            item2: // ...
            //<> more items
    object2: { /* .. */ }
    //<> more objects
}

These are the POJO s I created for parsing (I'll leave out the import statements for brevity's sake):

(1) The representation of the complete JSON object

public class JObjectContainer {

    private List<JObject> jObjects ;

    public JObjectContainer() { }

    //get & set methods

}

(2) The representation of the nested objects:

 public class JObject {

    private String id ;
    private List<JNode> jObjects ;

    public JObject() { } 

    //get & set methods

}

(3) The representation of the items:

 public class JNode {

    private JsonElement item1 ;
    private JsonElement item2 ;
    //<> more item fields

    public JNode() { }

    //get & set methods

}

Now, creating a Gson instance (FileReader for importing the jsonFile),

 Gson gson = new Gson() ;
 JObjectContainer joc = gson.fromJson(jsonFile,JObjectContainer.class) ;

I get a NullPointerException whenever I try to access the parseable object (e.g. through a ListIterator). Gson does however create an object of the class I specified and does not throw any subsequent errors.

I know that this has been done before. So, what am I missing?

TIA

+2  A: 

That's not possible. You need to modify your JSON structure to represent object1, object2, etc as items of an array. Right now they are properties of an object of which it's apparently unknown how many of them will be (else you didn't attempt to map it as a List). Gson is smart, but not that smart :)

So, as a basic example, this JSON structure with an array:

{ nodes:
  [
    { item1: 'value1a', item2: 'value2a' },
    { item1: 'value1b', item2: 'value2b' },
    { item1: 'value1c', item2: 'value2c' }
  ]
}

in combination with the Java representation (which is not necessarily to be called POJO, but just javabean or model object or value object).

public class Container {
    private List<Node> nodes;
    // +getter.
}

public class Node {
    private String item1;
    private String item2;
    // +getters.
}

and this Gson call

Container container = new Gson().fromJson(json, Container.class);

should work.

Update: to be clear, your JSON structure is the problem, not your Java object structure. Assuming that your Java object structure is exactly what you would like to end up with, then your JSON structure should look like follows to get Gson to do its job:

{ jObjects:
  [
    { id: 123, jObjects: 
      [
        { item1: 'value1a', item2: 'value2a' },
        { item1: 'value1b', item2: 'value2b' },
        { item1: 'value1c', item2: 'value2c' }
        /* etc... commaseparated */
      ]
    },
    { id: 456, jObjects: 
      [
        { item1: 'value1d', item2: 'value2d' },
        { item1: 'value1e', item2: 'value2e' },
        { item1: 'value1f', item2: 'value2f' }
        /* etc... commaseparated */
      ]
    }
    /* etc... commaseparated */
  ]
}

Only the JsonElement property should be replaced by String, since it's invalid.

BalusC
Hi, thanks for your answer! I intended to maintain the identifier strings (e.g. `Object1`), to be able to properly parse the Container class for its content, just like I would in JavaScript. Do you know how to go about that?
FK82
If those identifier strings are tied to every item (`Node`), not to the container (`nodes`), then you need to make it a property of the `Node` instead. JS objects with an unknown amount of properties and unknown property names are simply not a good idea/practice. You need to put them in an array and give the array a fixed name.
BalusC
That kinda beats the purpose of using JSON altogether. If I cannot mirror the object mapping style of JSON in JAVA, I might aswell write my own API. ;-) I'm basically trying to do the same thing as in this <a href="http://stackoverflow.com/questions/2710137/parsing-json-with-gson">example</href> while somehow retaining the identifier strings.
FK82
You cannot have an undetermined amount of properties in a java bean as well. The topic which you linked basically shows and answers the same: **use an array property**. Your problem is just the misunderstanding/misconception of basic OO principles, not JSON/Java.
BalusC
Just to be clear, I don't think I have an undetermined amount of properties in any of these classes. I'm using the `List` class for any Object class of which I do not know the number of items (i.e. `JObject`). Is that a fallacious approach? (Again, in this <a href="http://stackoverflow.com/questions/2710137/parsing-json-with-gson">example</a> it seems to be done using a `List`).
FK82
Yes, I know. You need to group those items in **an array** in the JSON side, using the `[` and `]` things to identify its start and end. Only then you can collect them in a `List`. Check my answer and the code example in that topic once again. [This tutorial](http://www.hunlock.com/blogs/Mastering_JSON_%28_JavaScript_Object_Notation_%29) may also be useful I think.
BalusC
Ok, so in other words GSON expects a certain JSON pattern. There's my answer. Thank you. (Btw.: how is the JSONElement *invalid* ?)
FK82
It just expects a JSON object with definied properties, not a JSON object with undefinied properties. JsonElement is invalid because that's not a value holder. You can find [here](http://stackoverflow.com/questions/1688099/converting-json-to-java/1688182#1688182) another example btw.
BalusC
So, if the `JNode` class should be able to represent a value of either (JS) type `String`, `Array` or `Object` how would I do that?
FK82
+1  A: 

I think BalusC gave good pointers for the specific question wrt GSon (and in general, one-to-one data binding); but just in case you think there should be more dynamic handling, you could also consider other JSON processing packages. Many packages have additional or alternative ways to map things: Json-lib, flexjson and Jackson at least have additions compared to Gson. Some offer looser mapping (you define names of things to types), others actual support for polymporphic types (declaring an Object but can actually map to subtype that was serialized).

StaxMan
Hi, thanks for your answer. Actually, I wasn't so sure how GSON operates internally and consequently did not quite understand how to use it. I am now using custom parsing with Rhino instead, which is much more handy in my opinion. Java does not support nested data objects in the same simple way JavaScript does, so there is no real reason to not use Rhino for that kind of thing.
FK82