1

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.

Luke Shan
  • 13
  • 3

1 Answers1

1

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);        
Community
  • 1
  • 1
alexbt
  • 16,415
  • 6
  • 78
  • 87
  • Thank you Alex. But I am using Gson. Gson doesn't have `ObjectMapper`. – Luke Shan Jul 15 '16 at 03:28
  • my bad! but it stills ansers the question as to how your model should be defined. I'll update it with Gson – alexbt Jul 15 '16 at 03:29
  • For Gson, you can use: Gson gson = new Gson(); Cars cars = gson.fromJson(json, Cars.class); //json is your json string – Antony Dao Jul 15 '16 at 03:31
  • Thanks @Antony Dao – alexbt Jul 15 '16 at 03:38
  • Tried but threw exception. Because in the JSON string, `count` is a property of `cars` instead of root. – Luke Shan Jul 15 '16 at 03:42
  • No exception but the result is wrong. In your class, `Cars` has property `cars`. But in the JSON String, 'cars' doesn't have 'cars' note. – Luke Shan Jul 15 '16 at 04:06
  • 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 cars`. – Luke Shan Jul 15 '16 at 04:27
  • Just so you know, I'm looking at it, it lead me to this: http://stackoverflow.com/questions/4547739/how-to-serialize-a-map-of-a-map-with-gson – alexbt Jul 15 '16 at 04:29
  • I updated the code, it was more complex that I expected/thought! It requires extending HashMap + writing custom Serializer/Deserializer! – alexbt Jul 15 '16 at 04:41