Velusamy Velu Velusamy Velu - 3 months ago 14
JSON Question

De-deserializing JSON using Gson

I'm looking for help in de-serializing a JSON to an instance of its POJO. The top level POJO Graph.java has an attribute of type HashMap. While serializing it throws


Expected BEGIN_ARRAY but was BEGIN_OBJECT at line n column nn path
$.degreesCountMap[0]


I know exactly what it means and how to fix it for for a top level collection but not sure how to specify the Type for an attribute of a another object.

I did review discussions on such issues in this and many other forums but I don't really see an answer that can help me.

I would greatly appreciate any help on this.

Here's the JSON of Graph:

{
"nodeCount":3,
"edgeCount":2,
"degreesCountMap":[
{
"ONE":2
},
{
"TWO":1
}
],
"nodes":[
{
"index":0,
"connectedIndices":[
1
]
},
{
"index":1,
"connectedIndices":[
0,
2
]
},
{
"index":2,
"connectedIndices":[
1
]
}
]
}


Here are the POJOs

Graph.java

public class Graph {
private HashMap<Degree, Integer> degreesCountMap;

private Integer edgeCount;
private Integer nodeCount;
private ArrayList<Node> nodes;
public HashMap<Degree, Integer> getDegreesCountMap() {
return degreesCountMap;
}

public void setDegreesCountMap(HashMap<Degree, Integer> degreesCountMap) {
this.degreesCountMap = degreesCountMap;
}

public void setNodes(ArrayList<Node> nodes) {
this.nodes = nodes;
}
}


Degree.java

public enum Degree {
ZERO, ONE, THREE, FOUR;
}


Node.java

public class Node {

private ArrayList<Integer> connectedIndices;
private int index;

public ArrayList<Integer> getConnectedIndices() {
return connectedIndices;
}

public int getIndex() {
return index;
}

public void setConnectedIndices(ArrayList<Integer> connectedIndices) {
this.connectedIndices = connectedIndices;
}

public void setIndex(int index) {
this.index = index;
}
}


GraphTest.java

@Test
public void testJsonToGraph() {

String json = "{\"nodeCount\":3,\"edgeCount\":2,"
+ "\"degreesCountMap\":[{\"ONE\":2},{\"TWO\":1}],"// <--to fail
+ "\"nodes\":[{\"index\":0,\"connectedIndices\":[1]},"
+ "{\"index\":1,\"connectedIndices\":[0,2]},"
+ "{\"index\":2,\"connectedIndices\":[1]}]}";

try {
graph = gson.fromJson(json, Graph.class);
assertNotNull(graph);
} catch (Exception e) { // Intentionally capturing to diagnose
e.printStackTrace();
}
}

Answer

The problem is that the JSON you posted is not valid.

Because Map can be used to map any object to any object Gson have to make map as array with two objects.

The valid JSON for map object would looks like this:

"degreesCountMap": [
  [
    "ONE",
    2
  ],
  [
    "TWO",
    1
  ]
]

but since you are using enum as keys the following code is also valid:

"degreesCountMap": {
    "TWO": 1,
    "ONE": 2
}

Solution: edit your json to valid one. Also, I think you are missing TWO in your degree enum.

Note: Because you use enum there is just "ONE" but if you used a typical object for a key it could looks like this:

"degreesCountMap": [
  [
    { "degree": "ONE" },
    2
  ],
  [
    { "degree": "TWO" },
    1
  ]
]