Luke Shan Luke Shan - 4 months ago 12
Java Question

How to define class to parse this JSON using Gson?

I get a JSON string like that:

{
"cars": {
"ford": {
"length": 4460,
"weight": 1450
},
"jeep": {
"length": 4670,
"weight": 1880
},
"toyota": {
"length": 3830,
"weight": 1120
},
.
.
.
"audi": {
"length": 5288,
"weight": 2432
},
"subaru": {
"length": 4755,
"weight": 1790
},
"count": 128
}
}


I try to define java classes to parse this JSON using Gson.

public class CarSize {
public int length;
public int weight;
}

public class JSONData {
public Map<String, CarSize> cars;
}


The problem is
cars
is not a pure map, it has
"count":128
and
128
is not a
CarSize
. How can I parse the JSON?

Please note I can't modify the JSON's source string. But I am OK to ignore the "count" property because I know it is the size of
Map<String, CarSize> cars
.

Answer

Looks like you have a Cars object with a list of Car List<Car> and a count property.

Trouble is, the count property is IN the map. What I did is extend the map, just to add the property. Then, you need to define your own serializer/deserializer for this map (Source get-nested-json-object-with-gson)

The model:

class Cars {
    private  MyMap cars = new MyMap();

    public MyMap getCars() {
        return cars;
    }
    public void setCars(MyMap cars) {
        this.cars = cars;
    }

    public void add(String name, Car car){
        cars.put(name, car);
        cars.setCount(cars.getCount()+1);
    }

}

class MyMap extends HashMap<String, Car> {
    private int count;

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

class Car {
    private int length;
    private int weight;

    public Car() {

    }

    public Car(int length, int weight) {
        this.length = length;
        this.weight = weight;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }
}

The custom Serializer/Deserializer:

class MyDeserializer implements JsonDeserializer<MyMap>
{
    @Override
    public MyMap deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
        JsonElement count = json.getAsJsonObject().remove("count");
        MyMap myMap = new Gson().fromJson(json.getAsJsonObject().toString(), type);
        if(count!=null){
            myMap.setCount(count.getAsInt());
        }
        return myMap;
    }
}

class MySerializer implements JsonSerializer<MyMap>
{
    @Override
    public JsonElement serialize(MyMap src, Type type, JsonSerializationContext context) {
        JsonElement serialize = context.serialize(src, Map.class);
        serialize.getAsJsonObject().add("count", new JsonPrimitive(src.getCount()));
        return serialize;
    }
}

The code to read and write the json:

String json = "{\"cars\":{\"jeep\":{\"length\":4670,\"weight\":1450},\"ford\":{\"length\":4460,\"weight\":1880},\"count\":128}}";
Cars cars = new Cars();
cars.add("jeep", new Car(4670, 1450));
cars.add("ford", new Car(4460, 1880));

Gson gson = new GsonBuilder()
           .registerTypeAdapter(MyMap.class, new MyDeserializer())
           .registerTypeAdapter(MyMap.class, new MySerializer())
           .create();

String json2 = gson.toJson(cars);
cars = gson.fromJson(json, Cars.class);
cars = gson.fromJson(json2, Cars.class);        
Comments