diff --git a/README.md b/README.md
index f9e8a88..cd699f4 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ The client can be used with Java 1.8+ and pulled into Maven or Gradle projects.
com.vertexvis
api-client-java
- 0.14.0
+ 0.15.0
compile
```
@@ -25,13 +25,13 @@ The client can be used with Java 1.8+ and pulled into Maven or Gradle projects.
### Gradle
```groovy
-compile "com.vertexvis:api-client-java:0.14.0"
+compile "com.vertexvis:api-client-java:0.15.0"
```
### Sbt
```sbt
-libraryDependencies += "com.vertexvis" % "api-client-java" % "0.14.0"
+libraryDependencies += "com.vertexvis" % "api-client-java" % "0.15.0"
```
### Others
@@ -44,7 +44,7 @@ mvn clean package
Then manually install the following JARs.
-- `target/api-client-java-0.14.0.jar`
+- `target/api-client-java-0.15.0.jar`
- `target/lib/*.jar`
## Usage
@@ -104,7 +104,7 @@ To consume published snapshot versions in other projects, add the snapshot repos
com.vertexvis
api-client-java
- 0.14.0-SNAPSHOT
+ 0.15.0-SNAPSHOT
```
@@ -119,7 +119,7 @@ repositories {
}
dependencies {
- implementation 'com.vertexvis:api-client-java:0.14.0-SNAPSHOT'
+ implementation 'com.vertexvis:api-client-java:0.15.0-SNAPSHOT'
}
```
diff --git a/build.gradle b/build.gradle
index b4d8195..5b79e91 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,7 +3,7 @@ plugins {
id "io.github.gradle-nexus.publish-plugin"
}
-def projectVersion = '0.14.0'
+def projectVersion = '0.15.0'
def isSnapshot = project.hasProperty('isSnapshot') && project.isSnapshot.toBoolean()
version = isSnapshot ? "${projectVersion}-SNAPSHOT" : projectVersion
diff --git a/buildSrc/src/main/groovy/vertex.openapi-generator.gradle b/buildSrc/src/main/groovy/vertex.openapi-generator.gradle
index 20b0530..9668f66 100644
--- a/buildSrc/src/main/groovy/vertex.openapi-generator.gradle
+++ b/buildSrc/src/main/groovy/vertex.openapi-generator.gradle
@@ -24,6 +24,10 @@ openApiGenerate {
dateLibrary: "java8",
hideGenerationTimestamp: "true",
useRuntimeException: "true",
+ disallowAdditionalPropertiesIfNotPresent: "false",
+ failOnUnknownProperties: "false",
+ useOneOfDiscriminatorLookup: "true",
+ legacyDiscriminatorBehavior: "false",
]
additionalProperties = [
skipValidationFor: "Part,PartData,PartDataAttributes,QueuedJobData,QueuedJob,QueuedJobDataAttributes" // Comma-separated list of models to skip validation for
diff --git a/buildSrc/src/main/resources/vertex-java/oneof_model.mustache b/buildSrc/src/main/resources/vertex-java/oneof_model.mustache
new file mode 100644
index 0000000..50e03ca
--- /dev/null
+++ b/buildSrc/src/main/resources/vertex-java/oneof_model.mustache
@@ -0,0 +1,537 @@
+
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.annotations.JsonAdapter;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonParseException;
+
+import {{invokerPackage}}.JSON;
+
+// This source file was generated using a Vertex modified version of the oneof_model.mustache template.
+
+{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}}
+public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}} implements {{{.}}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-implements}} {
+ private static final Logger log = Logger.getLogger({{classname}}.class.getName());
+
+ public static class CustomTypeAdapterFactory implements TypeAdapterFactory {
+ @SuppressWarnings("unchecked")
+ @Override
+ public TypeAdapter create(Gson gson, TypeToken type) {
+ if (!{{classname}}.class.isAssignableFrom(type.getRawType())) {
+ return null; // this class only serializes '{{classname}}' and its subtypes
+ }
+ final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class);
+ {{#composedSchemas}}
+ {{#oneOf}}
+ {{^isArray}}
+ {{^isMap}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ final TypeAdapter<{{{dataType}}}> adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = gson.getDelegateAdapter(this, TypeToken.get({{{dataType}}}.class));
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/isMap}}
+ {{/isArray}}
+ {{#isArray}}
+
+ final Type typeInstance{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = new TypeToken<{{{dataType}}}>(){}.getType();
+ final TypeAdapter<{{{dataType}}}> adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = (TypeAdapter<{{{dataType}}}>) gson.getDelegateAdapter(this, TypeToken.get(typeInstance{{#sanitizeGeneric}}{{{dataType}}}{{/sanitizeGeneric}}));
+ {{/isArray}}
+ {{#isMap}}
+ final Type typeInstance{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = new TypeToken<{{{dataType}}}>(){}.getType();
+ final TypeAdapter<{{{dataType}}}> adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = (TypeAdapter<{{{dataType}}}>) gson.getDelegateAdapter(this, TypeToken.get(typeInstance{{#sanitizeGeneric}}{{{dataType}}}{{/sanitizeGeneric}}));
+ {{/isMap}}
+ {{/oneOf}}
+ {{/composedSchemas}}
+
+ return (TypeAdapter) new TypeAdapter<{{classname}}>() {
+ @Override
+ public void write(JsonWriter out, {{classname}} value) throws IOException {
+ if (value == null || value.getActualInstance() == null) {
+ elementAdapter.write(out, null);
+ return;
+ }
+
+ {{#composedSchemas}}
+ {{#oneOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ // check if the actual instance is of the type `{{{dataType}}}`
+ if (value.getActualInstance() instanceof {{#isArray}}List>{{/isArray}}{{#isMap}}Map, ?>{{/isMap}}{{^isMap}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isMap}}) {
+ {{#isPrimitiveType}}
+ {{^isMap}}
+ JsonPrimitive primitive = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance()).getAsJsonPrimitive();
+ elementAdapter.write(out, primitive);
+ return;
+ {{/isMap}}
+ {{#isMap}}
+ JsonObject object = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance()).getAsJsonObject();
+ elementAdapter.write(out, object);
+ return;
+ {{/isMap}}
+ {{/isPrimitiveType}}
+ {{^isPrimitiveType}}
+ {{#isArray}}
+ List> list = (List>) value.getActualInstance();
+ if (list.get(0) instanceof {{{items.dataType}}}) {
+ JsonArray array = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance()).getAsJsonArray();
+ elementAdapter.write(out, array);
+ return;
+ }
+ {{/isArray}}
+ {{/isPrimitiveType}}
+ {{^isMap}}
+ {{^isArray}}
+ {{^isPrimitiveType}}
+ JsonElement element = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance());
+ elementAdapter.write(out, element);
+ return;
+ {{/isPrimitiveType}}
+ {{/isArray}}
+ {{/isMap}}
+ }
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/oneOf}}
+ {{/composedSchemas}}
+ throw new IOException("Failed to serialize as the type doesn't match oneOf schemas: {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}");
+ }
+
+ @Override
+ public {{classname}} read(JsonReader in) throws IOException {
+ Object deserialized = null;
+ JsonElement jsonElement = elementAdapter.read(in);
+
+ {{#useOneOfDiscriminatorLookup}}
+ {{#discriminator}}
+ JsonObject jsonObject = jsonElement.getAsJsonObject();
+
+ // use discriminator value for faster oneOf lookup
+ {{classname}} new{{classname}} = new {{classname}}();
+ if (jsonObject.get("{{{propertyBaseName}}}") == null) {
+ log.log(Level.WARNING, "Failed to lookup discriminator value for {{classname}} as `{{{propertyBaseName}}}` was not found in the payload or the payload is empty.");
+ } else {
+ // look up the discriminator value in the field `{{{propertyBaseName}}}`
+ switch (jsonObject.get("{{{propertyBaseName}}}").getAsString()) {
+ {{#mappedModels}}
+ case "{{{mappingName}}}":
+ deserialized = adapter{{modelName}}.fromJsonTree(jsonObject);
+ new{{classname}}.setActualInstance(deserialized);
+ return new{{classname}};
+ {{/mappedModels}}
+ default:
+ log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", jsonObject.get("{{{propertyBaseName}}}").getAsString()));
+ }
+ }
+
+ {{/discriminator}}
+ {{/useOneOfDiscriminatorLookup}}
+ int match = 0;
+ ArrayList errorMessages = new ArrayList<>();
+ TypeAdapter actualAdapter = elementAdapter;
+
+ {{#composedSchemas}}
+ {{#oneOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ {{^hasVars}}
+ // deserialize {{{dataType}}}
+ try {
+ // validate the JSON object to see if any exception is thrown
+ {{^isArray}}
+ {{^isMap}}
+ {{#isNumber}}
+ if (!jsonElement.getAsJsonPrimitive().isNumber()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ actualAdapter = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}};
+ {{/isNumber}}
+ {{^isNumber}}
+ {{#isPrimitiveType}}
+ if (!jsonElement.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ actualAdapter = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}};
+ {{/isPrimitiveType}}
+ {{/isNumber}}
+ {{^isNumber}}
+ {{^isPrimitiveType}}
+ {{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.validateJsonElement(jsonElement);
+ actualAdapter = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}};
+ {{/isPrimitiveType}}
+ {{/isNumber}}
+ {{/isMap}}
+ {{/isArray}}
+ {{#isArray}}
+ if (!jsonElement.isJsonArray()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+
+ JsonArray array = jsonElement.getAsJsonArray();
+ // validate array items
+ for(JsonElement element : array) {
+ {{#items}}
+ {{#isNumber}}
+ if (!jsonElement.getAsJsonPrimitive().isNumber()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isNumber}}
+ {{^isNumber}}
+ {{#isPrimitiveType}}
+ if (!element.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) {
+ throw new IllegalArgumentException(String.format("Expected array items to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isPrimitiveType}}
+ {{/isNumber}}
+ {{^isNumber}}
+ {{^isPrimitiveType}}
+ {{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.validateJsonElement(element);
+ {{/isPrimitiveType}}
+ {{/isNumber}}
+ {{/items}}
+ }
+ actualAdapter = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}};
+ {{/isArray}}
+ {{#isMap}}
+ if (!jsonElement.isJsonObject()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a object type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+
+ {{^isFreeFormObject}}
+ Map map = jsonElement.getAsJsonObject().asMap();
+ // validate map items
+ for(JsonElement element : map.values()) {
+ {{#items}}
+ {{#isNumber}}
+ if (!jsonElement.getAsJsonPrimitive().isNumber()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isNumber}}
+ {{^isNumber}}
+ {{#isPrimitiveType}}
+ if (!element.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) {
+ throw new IllegalArgumentException(String.format("Expected array items to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isPrimitiveType}}
+ {{/isNumber}}
+ {{^isNumber}}
+ {{^isPrimitiveType}}
+ {{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.validateJsonElement(element);
+ {{/isPrimitiveType}}
+ {{/isNumber}}
+ {{/items}}
+ }
+ {{/isFreeFormObject}}
+ actualAdapter = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}};
+ {{/isMap}}
+ match++;
+ log.log(Level.FINER, "Input data matches schema '{{{dataType}}}'");
+ } catch (Exception e) {
+ // deserialization failed, continue
+ errorMessages.add(String.format("Deserialization for {{{dataType}}} failed with `%s`.", e.getMessage()));
+ log.log(Level.FINER, "Input data does not match schema '{{{dataType}}}'", e);
+ }
+ {{/hasVars}}
+ {{#hasVars}}
+ // deserialize {{{.}}}
+ try {
+ // validate the JSON object to see if any exception is thrown
+ {{.}}.validateJsonElement(jsonElement);
+ actualAdapter = adapter{{.}};
+ match++;
+ log.log(Level.FINER, "Input data matches schema '{{{.}}}'");
+ } catch (Exception e) {
+ // deserialization failed, continue
+ errorMessages.add(String.format("Deserialization for {{{.}}} failed with `%s`.", e.getMessage()));
+ log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e);
+ }
+ {{/hasVars}}
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/oneOf}}
+ {{/composedSchemas}}
+
+ if (match == 1) {
+ {{classname}} ret = new {{classname}}();
+ ret.setActualInstance(actualAdapter.fromJsonTree(jsonElement));
+ return ret;
+ }
+
+ throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonElement.toString()));
+ }
+ }.nullSafe();
+ }
+ }
+
+ // store a list of schema names defined in oneOf
+ public static final Map> schemas = new HashMap>();
+
+ public {{classname}}() {
+ super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}});
+ }
+
+ public {{classname}}(Object o) {
+ super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}});
+ setActualInstance(o);
+ }
+
+ static {
+ {{#composedSchemas}}
+ {{#oneOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ schemas.put("{{{dataType}}}", {{{baseType}}}.class);
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/oneOf}}
+ {{/composedSchemas}}
+ }
+
+ @Override
+ public Map> getSchemas() {
+ return {{classname}}.schemas;
+ }
+
+ /**
+ * Set the instance that matches the oneOf child schema, check
+ * the instance parameter is valid against the oneOf child schemas:
+ * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}
+ *
+ * It could be an instance of the 'oneOf' schemas.
+ */
+ @Override
+ public void setActualInstance(Object instance) {
+ {{#isNullable}}
+ if (instance == null) {
+ super.setActualInstance(instance);
+ return;
+ }
+
+ {{/isNullable}}
+ {{#composedSchemas}}
+ {{#oneOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ if (instance instanceof {{#isArray}}List>{{/isArray}}{{#isMap}}Map, ?>{{/isMap}}{{^isMap}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isMap}}) {
+ {{#isArray}}
+ List> list = (List>) instance;
+ if (list.get(0) instanceof {{{items.dataType}}}) {
+ super.setActualInstance(instance);
+ return;
+ }
+ {{/isArray}}
+ {{^isArray}}
+ super.setActualInstance(instance);
+ return;
+ {{/isArray}}
+ }
+
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/oneOf}}
+ {{/composedSchemas}}
+ throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}");
+ }
+
+ /**
+ * Get the actual instance, which can be the following:
+ * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}
+ *
+ * @return The actual instance ({{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}})
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object getActualInstance() {
+ return super.getActualInstance();
+ }
+
+ {{#composedSchemas}}
+ {{#oneOf}}
+ {{^vendorExtensions.x-duplicated-data-type-ignoring-erasure}}
+ /**
+ * Get the actual instance of `{{{dataType}}}`. If the actual instance is not `{{{dataType}}}`,
+ * the ClassCastException will be thrown.
+ *
+ * @return The actual instance of `{{{dataType}}}`
+ * @throws ClassCastException if the instance is not `{{{dataType}}}`
+ */
+ public {{{dataType}}} get{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}() throws ClassCastException {
+ return ({{{dataType}}})super.getActualInstance();
+ }
+
+ {{/vendorExtensions.x-duplicated-data-type-ignoring-erasure}}
+ {{/oneOf}}
+ {{/composedSchemas}}
+ /**
+ * Validates the JSON Element and throws an exception if issues found
+ *
+ * @param jsonElement JSON Element
+ * @throws IOException if the JSON Element is invalid with respect to {{classname}}
+ */
+ public static void validateJsonElement(JsonElement jsonElement) throws IOException {
+ {{#useOneOfDiscriminatorLookup}}
+ {{#discriminator}}
+ // Vertex customization -- use the same behavior as the read method.
+ JsonObject jsonObject = jsonElement != null ? jsonElement.getAsJsonObject() : null;
+
+ if (jsonObject != null) {
+ if (jsonObject.get("type") == null) {
+ log.log(Level.WARNING, "Failed to lookup discriminator value for {{classname}} as `{{{propertyBaseName}}}` was not found in the payload or the payload is empty.");
+ } else {
+ // look up the discriminator value in the field `{{{propertyBaseName}}}`
+ switch (jsonObject.get("{{{propertyBaseName}}}").getAsString()) {
+ {{#mappedModels}}
+ case "{{{mappingName}}}":
+ {{modelName}}.validateJsonElement(jsonElement);
+ return;
+ {{/mappedModels}}
+ default:
+ log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", jsonObject.get("{{{propertyBaseName}}}").getAsString()));
+ }
+ }
+ }
+ {{/discriminator}}
+ {{/useOneOfDiscriminatorLookup}}
+ // validate oneOf schemas one by one
+ int validCount = 0;
+ ArrayList errorMessages = new ArrayList<>();
+ {{#composedSchemas}}
+ {{#oneOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ // validate the json string with {{{dataType}}}
+ try {
+ {{^hasVars}}
+ {{^isMap}}
+ {{^isArray}}
+ {{#isNumber}}
+ if (!jsonElement.getAsJsonPrimitive().isNumber()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isNumber}}
+ {{^isNumber}}
+ {{#isPrimitiveType}}
+ if (!jsonElement.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isPrimitiveType}}
+ {{/isNumber}}
+ {{^isNumber}}
+ {{^isPrimitiveType}}
+ {{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.validateJsonElement(jsonElement);
+ {{/isPrimitiveType}}
+ {{/isNumber}}
+ {{/isArray}}
+ {{/isMap}}
+ {{#isArray}}
+ if (!jsonElement.isJsonArray()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ JsonArray array = jsonElement.getAsJsonArray();
+ // validate array items
+ for(JsonElement element : array) {
+ {{#items}}
+ {{#isNumber}}
+ if (!jsonElement.getAsJsonPrimitive().isNumber()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isNumber}}
+ {{^isNumber}}
+ {{#isPrimitiveType}}
+ if (!element.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) {
+ throw new IllegalArgumentException(String.format("Expected array items to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isPrimitiveType}}
+ {{/isNumber}}
+ {{^isNumber}}
+ {{^isPrimitiveType}}
+ {{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.validateJsonElement(element);
+ {{/isPrimitiveType}}
+ {{/isNumber}}
+ {{/items}}
+ }
+ {{/isArray}}
+ {{#isMap}}
+ if (!jsonElement.isJsonObject()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a object type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+
+ {{^isFreeFormObject}}
+ Map map = jsonElement.getAsJsonObject().asMap();
+ // validate map items
+ for(JsonElement element : map.values()) {
+ {{#items}}
+ {{#isNumber}}
+ if (!jsonElement.getAsJsonPrimitive().isNumber()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isNumber}}
+ {{^isNumber}}
+ {{#isPrimitiveType}}
+ if (!element.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) {
+ throw new IllegalArgumentException(String.format("Expected array items to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isPrimitiveType}}
+ {{/isNumber}}
+ {{^isNumber}}
+ {{^isPrimitiveType}}
+ {{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.validateJsonElement(element);
+ {{/isPrimitiveType}}
+ {{/isNumber}}
+ {{/items}}
+ }
+ {{/isFreeFormObject}}
+ {{/isMap}}
+ {{/hasVars}}
+ {{#hasVars}}
+ {{{.}}}.validateJsonElement(jsonElement);
+ validCount++;
+ {{/hasVars}}
+ validCount++;
+ } catch (Exception e) {
+ errorMessages.add(String.format("Deserialization for {{{dataType}}} failed with `%s`.", e.getMessage()));
+ // continue to the next one
+ }
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/oneOf}}
+ {{/composedSchemas}}
+ if (validCount != 1) {
+ throw new IOException(String.format("The JSON string is invalid for {{classname}} with oneOf schemas: {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonElement.toString()));
+ }
+ }
+
+ /**
+ * Create an instance of {{classname}} given an JSON string
+ *
+ * @param jsonString JSON string
+ * @return An instance of {{classname}}
+ * @throws IOException if the JSON string is invalid with respect to {{classname}}
+ */
+ public static {{{classname}}} fromJson(String jsonString) throws IOException {
+ return JSON.getGson().fromJson(jsonString, {{{classname}}}.class);
+ }
+
+ /**
+ * Convert an instance of {{classname}} to an JSON string
+ *
+ * @return JSON string
+ */
+ public String toJson() {
+ return JSON.getGson().toJson(this);
+ }
+}
diff --git a/buildSrc/src/main/resources/vertex-java/pojo.mustache b/buildSrc/src/main/resources/vertex-java/pojo.mustache
index e1f16c3..af2ed13 100644
--- a/buildSrc/src/main/resources/vertex-java/pojo.mustache
+++ b/buildSrc/src/main/resources/vertex-java/pojo.mustache
@@ -21,6 +21,8 @@ import java.util.Set;
import {{invokerPackage}}.JSON;
+// This source file was generated using a Vertex modified version of the pojo.mustache template.
+
/**
* {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}}
* @deprecated{{/isDeprecated}}
@@ -356,7 +358,6 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
}
{{^hasChildren}}
{{^isAdditionalPropertiesTrue}}
-
Set> entries = jsonElement.getAsJsonObject().entrySet();
// check to see if the JSON string contains additional fields
for (Map.Entry entry : entries) {