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

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

/*
 * 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.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.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 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 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 = "#/definitions"; private ObjectNode schemaDocumentExtensions = Node.objectNode(); private ObjectNode extensions = Node.objectNode(); private Set disableFeatures = new HashSet<>(); private final ConcurrentHashMap extensionCache = new ConcurrentHashMap<>(); private final NodeMapper nodeMapper = new NodeMapper(); public JsonSchemaConfig() { nodeMapper.setWhenMissingSetter(NodeMapper.WhenMissing.INGORE); } 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; } /** * 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 "#/definitions" if no value is specified. 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 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)); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy