All Downloads are FREE. Search and download functionalities are using the official Maven repository.

software.amazon.smithy.jsonschema.JsonSchemaConfig Maven / Gradle / Ivy

There is a newer version: 1.51.0
Show newest version
/*
 * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 software.amazon.smithy.jsonschema;

import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.node.NodeMapper;
import software.amazon.smithy.model.node.ObjectNode;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.traits.TimestampFormatTrait;

/**
 * JSON Schema configuration options.
 */
public class JsonSchemaConfig {

    /**
     * Configures how Smithy union shapes are converted to JSON Schema.
     */
    public enum UnionStrategy {
        /**
         * Converts to a schema that uses "oneOf".
         *
         * 

This is the default setting used if not configured. */ ONE_OF("oneOf"), /** * Converts to an empty object "{}". */ OBJECT("object"), /** * Converts to an object with properties just like a structure. */ STRUCTURE("structure"); private final String stringValue; UnionStrategy(String stringValue) { this.stringValue = stringValue; } @Override public String toString() { return stringValue; } } /** * Configures how Smithy map shapes are converted to JSON Schema. */ public enum MapStrategy { /** * Converts to a schema that uses a combination of "propertyNames" * and "additionalProperties". * *

This is the default setting used if not configured. */ PROPERTY_NAMES("propertyNames"), /** * Converts to a schema that uses "patternProperties". If a map's key * member or its target does not have a {@code pattern} trait, a default * indicating one or more of any character (".+") is applied. */ PATTERN_PROPERTIES("patternProperties"); private final String stringValue; MapStrategy(String stringValue) { this.stringValue = stringValue; } @Override public String toString() { return stringValue; } } private boolean alphanumericOnlyRefs; private boolean useJsonName; private TimestampFormatTrait.Format defaultTimestampFormat = TimestampFormatTrait.Format.DATE_TIME; private UnionStrategy unionStrategy = UnionStrategy.ONE_OF; private MapStrategy mapStrategy = MapStrategy.PROPERTY_NAMES; private String definitionPointer; private ObjectNode schemaDocumentExtensions = Node.objectNode(); private ObjectNode extensions = Node.objectNode(); private Set disableFeatures = new HashSet<>(); private JsonSchemaVersion jsonSchemaVersion = JsonSchemaVersion.DRAFT07; private final ConcurrentHashMap, Object> extensionCache = new ConcurrentHashMap<>(); private final NodeMapper nodeMapper = new NodeMapper(); private ShapeId service; private boolean supportNonNumericFloats = false; private boolean enableOutOfServiceReferences = false; private boolean useIntegerType; private boolean disableDefaultValues = false; private boolean disableIntEnums = false; public JsonSchemaConfig() { nodeMapper.setWhenMissingSetter(NodeMapper.WhenMissing.IGNORE); } public boolean getAlphanumericOnlyRefs() { return alphanumericOnlyRefs; } /** * Creates shape name pointers that strip out non-alphanumeric characters. * *

This is necessary for compatibility with some vendors like * Amazon API Gateway that only allow alphanumeric shape names. * * @param alphanumericOnlyRefs Set to true to strip non-alphanumeric characters. */ public void setAlphanumericOnlyRefs(boolean alphanumericOnlyRefs) { this.alphanumericOnlyRefs = alphanumericOnlyRefs; } public boolean getUseJsonName() { return useJsonName; } /** * Uses the value of the jsonName trait when creating JSON schema * properties for structure and union shapes. * *

This property has no effect if a {@link PropertyNamingStrategy} is * manually configured on a {@link JsonSchemaConverter}. * * @param useJsonName Set to true to use jsonName traits when creating refs.. */ public void setUseJsonName(boolean useJsonName) { this.useJsonName = useJsonName; } public TimestampFormatTrait.Format getDefaultTimestampFormat() { return defaultTimestampFormat; } /** * Sets the assumed timestampFormat trait for timestamps with no * timestampFormat trait. The provided value is expected to be a string. * *

Defaults to "date-time" if not set. Can be set to "date-time", * "epoch-seconds", or "http-date". * * @param defaultTimestampFormat The default timestamp format to use when none is set. */ public void setDefaultTimestampFormat(TimestampFormatTrait.Format defaultTimestampFormat) { this.defaultTimestampFormat = defaultTimestampFormat; } public UnionStrategy getUnionStrategy() { return unionStrategy; } /** * Configures how Smithy union shapes are converted to JSON Schema. * * @param unionStrategy The union strategy to use. */ public void setUnionStrategy(UnionStrategy unionStrategy) { this.unionStrategy = unionStrategy; } public MapStrategy getMapStrategy() { return mapStrategy; } /** * Configures how Smithy map shapes are converted to JSON Schema. * * @param mapStrategy The map strategy to use. */ public void setMapStrategy(MapStrategy mapStrategy) { this.mapStrategy = mapStrategy; } public String getDefinitionPointer() { return definitionPointer != null ? definitionPointer : jsonSchemaVersion.getDefaultDefinitionPointer(); } /** * Configures location of where definitions are written using JSON Pointer. * *

The provided String value MUST start with "#/" and can use nested "/" * characters to place schemas in nested object properties. The provided * JSON Pointer does not support escaping. * *

Defaults to {@code "#/definitions"} for schema versions less than 2019-09 and {@code "#/$defs"} for schema * versions 2019-09 and greater. OpenAPI artifacts will want to use "#/components/schemas". * * @param definitionPointer The root definition pointer to use. */ public void setDefinitionPointer(String definitionPointer) { this.definitionPointer = Objects.requireNonNull(definitionPointer); } public ObjectNode getSchemaDocumentExtensions() { return schemaDocumentExtensions; } /** * Adds custom key-value pairs to the JSON Schema document generated from * a Smithy model. * * @param schemaDocumentExtensions Custom extensions to merge into the created schema. */ public void setSchemaDocumentExtensions(ObjectNode schemaDocumentExtensions) { this.schemaDocumentExtensions = Objects.requireNonNull(schemaDocumentExtensions); } public Set getDisableFeatures() { return disableFeatures; } /** * Disables OpenAPI features by their property name (e.g., "allOf"). * * @param disableFeatures Feature names to disable. */ public void setDisableFeatures(Set disableFeatures) { this.disableFeatures = disableFeatures; } public ObjectNode getExtensions() { return extensions; } /** * Attempts to deserialize the {@code extensions} into the targeted * type using a {@link NodeMapper}. * *

Extraneous properties are ignored and not warned on * because many different plugins could be used with different * configuration POJOs. * *

The result of calling this method is cached for each type, * and the cache is cleared when any mutation is made to * extensions. * * @param as Type to deserialize extensions into. * @param Type to deserialize extensions into. * @return Returns the deserialized type. */ @SuppressWarnings("unchecked") public T getExtensions(Class as) { return (T) extensionCache.computeIfAbsent(as, t -> nodeMapper.deserialize(extensions, t)); } /** * Sets an arbitrary map of "extensions" used by plugins that need * configuration. * * @param extensions Extensions to set. */ public void setExtensions(ObjectNode extensions) { this.extensions = Objects.requireNonNull(extensions); extensionCache.clear(); } /** * Add an extension to the "extensions" object node using a POJO. * * @param extensionContainer POJO to serialize and merge into extensions. */ public void putExtensions(Object extensionContainer) { ObjectNode serialized = nodeMapper.serialize(extensionContainer).expectObjectNode(); setExtensions(extensions.merge(serialized)); } /** * Add an extension to the "extensions" object node. * * @param key Property name to set. * @param value Value to assigned. */ public void putExtension(String key, Node value) { setExtensions(extensions.withMember(key, value)); } /** * Add an extension to the "extensions" object node. * * @param key Property name to set. * @param value Value to assigned. */ public void putExtension(String key, boolean value) { putExtension(key, Node.from(value)); } /** * Add an extension to the "extensions" object node. * * @param key Property name to set. * @param value Value to assigned. */ public void putExtension(String key, String value) { putExtension(key, Node.from(value)); } /** * Gets the service shape ID that is used to contextualize the created * schemas by using things like the "rename" property of the service. * * @return the nullable Smithy service shape ID. */ public ShapeId getService() { return service; } /** * Sets the service shape ID that is used to contextualize the created * schemas by using things like the "rename" property of the service. * * @param service the Smithy service shape ID. */ public void setService(ShapeId service) { this.service = service; } /** * Detects the TimestampFormat of the given shape, falling back to the * configured default format specified in {@link #setDefaultTimestampFormat(TimestampFormatTrait.Format)}. * * @param shape Shape to extract the timestamp format from. * @return Returns the optionally detected format. */ public Optional detectJsonTimestampFormat(Shape shape) { if (shape.isTimestampShape() || shape.hasTrait(TimestampFormatTrait.class)) { return Optional.of(shape.getTrait(TimestampFormatTrait.class) .map(TimestampFormatTrait::getValue) .orElseGet(() -> getDefaultTimestampFormat().toString())); } return Optional.empty(); } public boolean getSupportNonNumericFloats() { return supportNonNumericFloats; } /** * Set to true to add support for NaN, Infinity, and -Infinity in float * and double shapes. These values will be serialized as strings. The * OpenAPI document will be updated to refer to them as a "oneOf" of number * and string. * *

By default, non-numeric values are not supported. * * @param supportNonNumericFloats True if non-numeric float values should be supported. */ public void setSupportNonNumericFloats(boolean supportNonNumericFloats) { this.supportNonNumericFloats = supportNonNumericFloats; } public boolean isEnableOutOfServiceReferences() { return enableOutOfServiceReferences; } /** * Set to true to enable references to shapes outside the service closure. * * Setting this to true means that all the shapes in the model must not conflict, whereas * leaving it at the default, false, means that only the shapes connected to the configured * service via {@link #setService(ShapeId)} must not conflict. * * @param enableOutOfServiceReferences true if out-of-service references should be allowed. default: false */ public void setEnableOutOfServiceReferences(boolean enableOutOfServiceReferences) { this.enableOutOfServiceReferences = enableOutOfServiceReferences; } public boolean getUseIntegerType() { return useIntegerType; } /** * Set to true to use the "integer" type when converting {@code byte}, * {@code short}, {@code integer}, and {@code long} shapes to Json Schema. * *

By default, these shape types are converted to Json Schema with a type * of "number". * * @param useIntegerType True to use "integer". */ public void setUseIntegerType(boolean useIntegerType) { this.useIntegerType = useIntegerType; } public boolean getDisableDefaultValues() { return disableDefaultValues; } /** * Set to true to disable default values on schemas, including wrapping $ref pointers in an `allOf`. * * @param disableDefaultValues True to disable setting default values. */ public void setDisableDefaultValues(boolean disableDefaultValues) { this.disableDefaultValues = disableDefaultValues; } public boolean getDisableIntEnums() { return disableIntEnums; } /** * Set to true to disable setting an `enum` property for intEnums. When disabled, * intEnums are inlined instead of using a $ref. * * @param disableIntEnums True to disable setting `enum` property for intEnums. */ public void setDisableIntEnums(boolean disableIntEnums) { this.disableIntEnums = disableIntEnums; } /** * JSON schema version to use when converting Smithy shapes into Json Schema. * *

Defaults to JSON Schema version {@code draft07} if no schema version is specified * * @return JSON Schema version that will be used for generated JSON schema */ public JsonSchemaVersion getJsonSchemaVersion() { return jsonSchemaVersion; } /** * Set the JSON schema version to use when converting Smithy shapes into Json Schema. * * @param schemaVersion JSON Schema version to use for generated schema */ public void setJsonSchemaVersion(JsonSchemaVersion schemaVersion) { this.jsonSchemaVersion = Objects.requireNonNull(schemaVersion); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy