throws JSONException {
if (!DEFAULT_SCHEMA_VERSION.equals(jsonObject.optString(JSONSchema.SCHEMA_KEY, DEFAULT_SCHEMA_VERSION))) {
throw new IllegalArgumentException("Unrecognized schema version: " + jsonObject.optString(JSONSchema.SCHEMA_KEY));
}
JSONSchema jsonSchema = new JSONSchema();
String id = jsonObject.optString("id", null);
if (!Strings.isNullOrEmpty(id)) {
jsonSchema.setID(id);
_schemaCache.put(id, jsonSchema);
}
String referencesSchemaID = jsonObject.optString("$ref", null);
if (!Strings.isNullOrEmpty(referencesSchemaID)) {
jsonSchema.setReferencesSchema(fromSchemaID(referencesSchemaID));
}
String extendsSchemaID = jsonObject.optString("extends", null);
if (!Strings.isNullOrEmpty(extendsSchemaID)) {
jsonSchema.setExtendsSchema(fromSchemaID(extendsSchemaID));
}
jsonSchema.setRequired((Boolean) jsonObject.opt("required"));
jsonSchema.setTitle(jsonObject.optString("title", null));
jsonSchema.setDescription(jsonObject.optString("description", null));
Object typeValue = jsonObject.opt("type");
if (typeValue instanceof JSONArray) {
jsonSchema.setTypes(convertSchemaTypesFromJSONValues(new GenericJSONArrayList((JSONArray) typeValue)));
} else if (typeValue instanceof Collection) {
//noinspection unchecked
jsonSchema.setTypes(convertSchemaTypesFromJSONValues((Collection) typeValue));
} else if (typeValue != null) {
jsonSchema.setTypes(convertSchemaTypesFromJSONValues(Collections.singleton(typeValue)));
}
for (final JSONSchemaType<?> type : jsonSchema.getTypes()) {
Object defaultValue = jsonObject.opt("default");
Number minimum = (Number) jsonObject.opt("minimum");
Boolean minimumExclusive = (Boolean) jsonObject.opt("exclusiveMinimum");
Number maximum = (Number) jsonObject.opt("maximum");
Boolean maximumExclusive = (Boolean) jsonObject.opt("exclusiveMaximum");
Number divisibleBy = (Number) jsonObject.opt("divisibleBy");
List<Object> enums = new GenericJSONArrayList(jsonObject.optJSONArray("enum"));
if (type instanceof JSONSchemaBooleanType) {
JSONSchemaBooleanType booleanType = (JSONSchemaBooleanType) type;
if (defaultValue instanceof Boolean) {
booleanType.setDefaultValue((Boolean) defaultValue);
}
} else if (type instanceof JSONSchemaIntegerType) {
JSONSchemaIntegerType intType = (JSONSchemaIntegerType) type;
if (defaultValue instanceof Number) {
intType.setDefaultValue(((Number) defaultValue).intValue());
}
if (minimum instanceof Number) {
intType.setMinimum(minimum.intValue());
}
if (minimumExclusive instanceof Boolean) {
intType.setMinimumExclusive(minimumExclusive);
}
if (maximum instanceof Number) {
intType.setMaximum(maximum.intValue());
}
if (maximumExclusive instanceof Boolean) {
intType.setMaximumExclusive(maximumExclusive);
}
if (divisibleBy instanceof Number) {
intType.setDivisibleBy(divisibleBy.intValue());
}
intType.setEnumValues(Collections2.filter(Lists.transform(enums, new Function<Object, Integer>() {
@Override
public Integer apply(@Nullable Object input) {
return input instanceof Number ? ((Number) input).intValue() : null;
}
}), Predicates.notNull()));
} else if (type instanceof JSONSchemaNumberType) {
JSONSchemaNumberType numberType = (JSONSchemaNumberType) type;
if (defaultValue instanceof Number) {
numberType.setDefaultValue((Number) defaultValue);
}
if (minimum instanceof Number) {
numberType.setMinimum(minimum);
}
if (minimumExclusive instanceof Boolean) {
numberType.setMinimumExclusive(minimumExclusive);
}
if (maximum instanceof Number) {
numberType.setMaximum(maximum);
}
if (maximumExclusive instanceof Boolean) {
numberType.setMaximumExclusive(maximumExclusive);
}
if (divisibleBy instanceof Number) {
numberType.setDivisibleBy(divisibleBy);
}
numberType.setEnumValues(Collections2.filter(Lists.transform(enums, new Function<Object, Number>() {
@Override
public Number apply(@Nullable Object input) {
return input instanceof Number ? (Number) input : null;
}
}), Predicates.notNull()));
} else if (type instanceof JSONSchemaStringType) {
JSONSchemaStringType stringType = (JSONSchemaStringType) type;
if (defaultValue instanceof String) {
stringType.setDefaultValue((String) defaultValue);
}
Number minimumLength = (Number) jsonObject.opt("minLength");
if (minimumLength != null) {
stringType.setMinimumLength(minimumLength.intValue());
}
Number maximumLength = (Number) jsonObject.opt("maxLength");
if (maximumLength != null) {
stringType.setMaximumLength(maximumLength.intValue());
}
stringType.setPattern(jsonObject.optString("pattern", null));
String format = jsonObject.optString("format");
stringType.setFormat(convertSchemaTextFormatFromJSONValue(format));
if (stringType.getFormat() == JSONSchemaTextFormat.CUSTOM) {
stringType.setCustomFormat(format);
}
stringType.setEnumValues(Collections2.filter(Lists.transform(enums, new Function<Object, String>() {
@Override
public String apply(@Nullable Object input) {
return input instanceof String ? (String) input : null;
}
}), Predicates.notNull()));
} else if (type instanceof JSONSchemaObjectType) {
JSONSchemaObjectType objectType = (JSONSchemaObjectType) type;
JSONObject propertiesJSONObject = jsonObject.optJSONObject("properties");
if (propertiesJSONObject != null) {
objectType.setNamedProperties(_namedPropertyMarshaller.fromMappedJSONObject(propertiesJSONObject, null));
}
JSONObject patternPropertiesJSONObject = jsonObject.optJSONObject("patternProperties");
if (patternPropertiesJSONObject != null) {
objectType.setPatternProperties(_patternPropertyMarshaller.fromMappedJSONObject(patternPropertiesJSONObject, null));
}
Object additionalProperties = jsonObject.opt("additionalProperties");
if (additionalProperties instanceof JSONObject) {
objectType.setAdditionalPropertiesSchema(fromJSONObject((JSONObject) additionalProperties));
} else if (additionalProperties instanceof Boolean && !((Boolean) additionalProperties)) {
objectType.setAdditionalPropertiesSchema(null);
} else if (additionalProperties != null && additionalProperties != JSONObject.NULL) {
throw new IllegalArgumentException("Unsupported additional properties: " + additionalProperties);
}
} else if (type instanceof JSONSchemaArrayType) {
JSONSchemaArrayType arrayType = (JSONSchemaArrayType) type;
Object items = jsonObject.opt("items");
if (items instanceof JSONObject) {
arrayType.setItem(fromJSONObject((JSONObject) items));
} else if (items instanceof JSONArray || items instanceof Collection) {
arrayType.setItems(fromJSONArray((JSONArray) items));
Object additionalItems = jsonObject.opt("additionalItems");
if (additionalItems instanceof JSONObject) {
arrayType.additionalItemsSchema(fromJSONObject((JSONObject) additionalItems));
} else if (additionalItems instanceof Boolean && !((Boolean) additionalItems)) {
arrayType.additionalItemsSchema(null);
} else if (additionalItems != null && additionalItems != JSONObject.NULL) {
throw new IllegalArgumentException("Unsupported additional items: " + additionalItems);
} else {
arrayType.additionalItemsSchema(new JSONSchema());
}
}
}
}