Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.zuunr.jsonschema.JsonSchemaConverter Maven / Gradle / Ivy
/*
* Copyright 2020 Zuunr AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zuunr.jsonschema;
import com.zuunr.forms.Form;
import com.zuunr.forms.FormField;
import com.zuunr.forms.FormFields;
import com.zuunr.forms.ValueFormat;
import com.zuunr.forms.formfield.Type;
import com.zuunr.json.JsonArray;
import com.zuunr.json.JsonObject;
import com.zuunr.json.JsonObjectBuilder;
import com.zuunr.json.JsonValue;
import java.util.Iterator;
/**
* @author Niklas Eldberger
*/
public class JsonSchemaConverter {
private static final JsonValue JSON_SCHEMA_TYPE_NULL = JsonValue.of("null");
private static final JsonObject JSON_SCHEMA_VALIDATION_KEY_MAPPINGS = JsonObject.EMPTY.builder()
.put("maximum", "max")
.put("exclusiveMaximum", "exclusiveMaximum")
.put("maxItems", "maxsize")
.put("maxLength", "maxlength")
.put("minimum", "min")
.put("exclusiveMinimum", "exclusiveMinimum")
.put("minItems", "minsize")
.put("minLength", "minlength")
.put("nullable", "nullable")
.put("pattern", "pattern")
.put("description", "desc")
.put("enum", "enum")
.put("const", "const")
.put("format", "typeFormat")
.put("default", "default")
.build();
private static final JsonObject JSON_SCHEMA_SUBSCHEMA_KEYWORDS_SUPPORT = init(
JsonObject.EMPTY.builder()
.put("allOf", false)
.put("anyOf", false)
.put("oneOf", false)
.put("not", false)
.put("if", false)
.put("then", false)
.put("else", false)
.put("dependentSchemas", false)
.put("items", true)
.put("additionalItems", true)
.put("unevaluatedItems", false)
.put("contains", false)
.put("properties", true)
.put("patternProperties", false)
.put("additionalProperties", true)
.put("propertyNames", false)
.put("type", true)
.put("required", true)
.build(),
JSON_SCHEMA_VALIDATION_KEY_MAPPINGS);
public static JsonObject init(JsonObject subschemaKeywords, JsonObject keyMappings) {
JsonObjectBuilder builder = subschemaKeywords.builder();
for (String key : keyMappings.keys().asList(String.class)) {
builder.put(key, true);
}
return builder.build();
}
public ValueFormat translate(JsonValue jsonSchema) {
if (jsonSchema.is(Boolean.class)) {
translate(jsonSchema.getValue(Boolean.class));
} else if (jsonSchema.is(JsonObject.class)) {
return translate(jsonSchema.getValue(JsonObject.class));
}
throw new ConversionException("Only Boolean and JsonObject is supported right now");
}
public ValueFormat translate(boolean jsonSchema) {
if (jsonSchema) {
return ValueFormat.ANY_VALUE_FORMAT;
} else {
return ValueFormat.IMPOSSIBLE_VALUE_FORMAT;
}
}
public ValueFormat translate(JsonObject jsonSchema) {
return translateToValueFormat(jsonSchema).build().as(ValueFormat.class);
}
private JsonObjectBuilder translateToValueFormat(JsonObject jsonSchema) {
JsonObjectBuilder formFieldOrValueFormat = JsonObject.EMPTY.builder();
return translateToValueFormat(jsonSchema, formFieldOrValueFormat);
}
private JsonObjectBuilder translateToValueFormat(JsonObject jsonSchema, JsonObjectBuilder formFieldOrValueFormat) {
JsonObject unsupported = validateSchemaSupport(jsonSchema);
if (!unsupported.isEmpty()) {
throw new ConversionException("JSON Schema contains unsupported properties: " + unsupported);
}
translateSimpleValidationKeywords(jsonSchema, formFieldOrValueFormat);
Type type = translateType(jsonSchema, formFieldOrValueFormat);
formFieldOrValueFormat.put("type", type);
if (type.isString()) {
// Mapping is one-to-one, no need for mapping enum to pattern :)
} else if (type.isObject()) {
translateObject(jsonSchema, formFieldOrValueFormat);
} else if (type.isArrayOrSet()) {
translateArray(jsonSchema, formFieldOrValueFormat);
}
return formFieldOrValueFormat;
}
private JsonObject validateSchemaSupport(JsonObject jsonSchema) {
JsonObjectBuilder unsupported = JsonObject.EMPTY.builder();
Iterator values = jsonSchema.values().iterator();
for (String key : jsonSchema.keys().asList(String.class)) {
JsonValue value = values.next();
if (!JSON_SCHEMA_SUBSCHEMA_KEYWORDS_SUPPORT.get(key, JsonValue.FALSE).getValue(Boolean.class).booleanValue()) {
unsupported.put(key, value);
}
}
return unsupported.build();
}
private Type translateType(JsonObject jsonSchemaProperty, JsonObjectBuilder jsonObjectBuilder) {
JsonArray jsonSchemaTypes;
Type formatValueType = null;
JsonValue jsonSchemaTypeJsonValue = jsonSchemaProperty.get("type", JsonArray.EMPTY);
if (jsonSchemaTypeJsonValue.isString()) {
jsonSchemaTypes = JsonArray.of(jsonSchemaTypeJsonValue);
} else {
jsonSchemaTypes = jsonSchemaTypeJsonValue.getValue(JsonArray.class);
}
for (JsonValue typeJsonValue : jsonSchemaTypes) {
String type = typeJsonValue.getString();
if (JSON_SCHEMA_TYPE_NULL.equals(typeJsonValue)) {
jsonObjectBuilder.put("nullable", true);
} else if (formatValueType == null) {
formatValueType = translateNonNullType(type);
} else {
// Forms do not support multi-types
throw new ConversionException("Multi-types " + jsonSchemaTypes + "cannot be converted.");
}
}
return formatValueType == null ? Type.UNDEFINED : formatValueType;
}
private Type translateNonNullType(String type) {
if (Type.STRING.toString().equals(type)) {
return Type.STRING;
} else if (Type.OBJECT.toString().equals(type)) {
return Type.OBJECT;
} else if (Type.ARRAY.toString().equals(type)) {
return Type.ARRAY;
} else if (Type.INTEGER.toString().equals(type)) {
return Type.INTEGER;
} else if (Type.BOOLEAN.toString().equals(type)) {
return Type.BOOLEAN;
} else {
throw new ConversionException("Not supported type '" + type + "'");
}
}
public void translateObject(JsonObject objectJsonSchema, JsonObjectBuilder formFieldOrValueFormat) {
FormFields.FormFieldsBuilder formFieldsBuilder = FormFields.EMPTY.builder();
JsonObject objectProperties = requiredAsObject(objectJsonSchema.get("required", JsonArray.EMPTY).getValue(JsonArray.class)).putAll(objectJsonSchema.get("properties", JsonObject.EMPTY).getValue(JsonObject.class));
JsonArray keys = objectProperties.keys();
Iterator values = objectProperties.values().iterator();
for (JsonValue keyJsonValue : keys) {
String key = keyJsonValue.getString();
JsonObject value = values.next().getValue(JsonObject.class);
formFieldsBuilder.add(
translateToValueFormat(value)
.put("name", key)
.put("required", isRequired(objectJsonSchema, key))
.build()
.as(FormField.class));
}
Form.FormBuilder formBuilder = Form.EMPTY.builder().value(formFieldsBuilder);
boolean exclusive;
JsonValue additionalProperties = objectJsonSchema.get("additionalProperties", JsonValue.FALSE);
if (additionalProperties.is(Boolean.class)) {
exclusive = !additionalProperties.getValue(Boolean.class);
} else {
exclusive = additionalProperties.equals(JsonObject.EMPTY.put("not", JsonObject.EMPTY).jsonValue());
}
formBuilder.exclusive(exclusive);
formFieldOrValueFormat.put("form", formBuilder.build());
}
private JsonObject requiredAsObject(JsonArray jsonSchemaRequired) {
JsonObjectBuilder builder = JsonObject.EMPTY.builder();
for (String requiredProperty : jsonSchemaRequired.asList(String.class)) {
builder.put(requiredProperty, JsonObject.EMPTY);
}
return builder.build();
}
private boolean isRequired(JsonObject objectJsonSchema, String property) {
return objectJsonSchema.get("required", JsonArray.EMPTY).getValue(JsonArray.class).contains(property);
}
public void translateArray(JsonObject arrayJsonSchema, JsonObjectBuilder formFieldOrValueFormat) {
JsonObject items = arrayJsonSchema.get("items", JsonObject.EMPTY).getValue(JsonObject.class);
ValueFormat valueFormat = translateToValueFormat(items).build().as(ValueFormat.class);
formFieldOrValueFormat.put("element", valueFormat);
}
private void translateSimpleValidationKeywords(JsonObject jsonSchema, JsonObjectBuilder formFieldOrValueFormat) {
JsonArray keys = jsonSchema.keys();
Iterator values = jsonSchema.values().iterator();
for (String jsonSchemaKey : keys.asList(String.class)) {
JsonValue asFormKey = JSON_SCHEMA_VALIDATION_KEY_MAPPINGS.get(jsonSchemaKey);
JsonValue value = values.next();
if (asFormKey != null) {
formFieldOrValueFormat.put(asFormKey.getString(), value);
}
}
}
}