protected static Object deserialize(String json, String... packagePrefixes)
	    throws APIException {
	try {
	    JsonObject jo = parser.parse(json).getAsJsonObject();
	    JsonElement dataClassJE = jo.get("type");
	    if (dataClassJE == null) {
		throw new APIException(
			"The JSON object sent to the server does not contain the required \"type\" attribute.");
	    }
	    String className = dataClassJE.getAsString();
	    // try to find class in all allowed packages
	    Class dataClass = null;
	    for (String packagePrefix : packagePrefixes) {
		try {
		    dataClass = Class.forName(packagePrefix.concat(className));
		} catch (ClassNotFoundException classNotFoundException) {
		    // ok, try the next package
		}
	    }
	    if (dataClass == null) {
		throw new APIException(
			"The class name specified in attribute \"type\" in the JSON string sent to the server (\""
				+ className
				+ "\") does not contain a class name known to the system.");
	    }

	    JsonElement dataJE = jo.get("data");
	    if (dataJE == null) {
		throw new APIException(
			"The JSON object sent to the server does not contain the required \"data\" attribute.");
	    }
	    Object data = gson.fromJson(dataJE, dataClass);
	    return data;
	} catch (JsonParseException ex) {
	    // assuming the exception is either JsonSyntaxException, because
	    // JsonIOException will not occur (no input streams used)
	    throw new APIException(
		    "The JSON string sent to the server is malformatted (contains syntax errors): "
			    + ex.getMessage());
	}
    }