@Override
  public JsonRpcResponse deserialize(
      JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
    JsonObject jsonObject = json.getAsJsonObject();

    String id = jsonObject.get(ResponseProperty.ID.key()).getAsString();
    if (jsonObject.has(ResponseProperty.ERROR.key())) {
      JsonElement errorObject = jsonObject.get(ResponseProperty.ERROR.key());
      String errorMessage = errorObject.getAsJsonObject().get("message").getAsString();
      return JsonRpcResponse.error(id, errorMessage);
    }

    // Deserialize the data.
    Map<ParamsProperty, Object> properties = new HashMap<ParamsProperty, Object>();
    JsonElement data = jsonObject.get(ResponseProperty.DATA.key());
    if (data != null && data.isJsonObject()) {
      for (Entry<String, JsonElement> parameter : data.getAsJsonObject().entrySet()) {
        ParamsProperty parameterType = ParamsProperty.fromKey(parameter.getKey());
        if (parameterType == null) {
          // Skip this unknown parameter.
          continue;
        }
        Object object = null;
        if (parameterType == ParamsProperty.BLIPS) {
          Type blipMapType = new TypeToken<Map<String, BlipData>>() {}.getType();
          object = context.deserialize(parameter.getValue(), blipMapType);
        } else {
          object = context.deserialize(parameter.getValue(), parameterType.clazz());
        }
        properties.put(parameterType, object);
      }
    }

    return JsonRpcResponse.result(id, properties);
  }
 @Override
 public JsonElement serialize(JsonRpcResponse src, Type type, JsonSerializationContext context) {
   JsonObject result = new JsonObject();
   result.addProperty(ResponseProperty.ID.key(), src.getId());
   if (src.isError()) {
     JsonObject error = new JsonObject();
     error.addProperty(ParamsProperty.MESSAGE.key(), src.getErrorMessage());
     result.add(ResponseProperty.ERROR.key(), error);
   } else {
     JsonObject data = new JsonObject();
     for (Entry<ParamsProperty, Object> properties : src.getData().entrySet()) {
       data.add(properties.getKey().key(), context.serialize(properties.getValue()));
     }
     result.add(ResponseProperty.DATA.key(), data);
   }
   return result;
 }