add tests for uuid in oneOf/anyOf (java okhttp-gson) (#21763)

This commit is contained in:
William Cheng
2025-08-16 12:23:04 +08:00
committed by GitHub
parent 030be5d3c7
commit fe5305f2cf
4 changed files with 112 additions and 13 deletions

View File

@@ -15,6 +15,7 @@ package org.openapitools.client.model;
import java.util.Objects;
import java.math.BigDecimal;
import java.util.UUID;
@@ -63,6 +64,7 @@ public class Scalar extends AbstractOpenApiSchema {
return null; // this class only serializes 'Scalar' and its subtypes
}
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
final TypeAdapter<UUID> adapterUUID = gson.getDelegateAdapter(this, TypeToken.get(UUID.class));
final TypeAdapter<String> adapterString = gson.getDelegateAdapter(this, TypeToken.get(String.class));
final TypeAdapter<BigDecimal> adapterBigDecimal = gson.getDelegateAdapter(this, TypeToken.get(BigDecimal.class));
final TypeAdapter<Boolean> adapterBoolean = gson.getDelegateAdapter(this, TypeToken.get(Boolean.class));
@@ -75,6 +77,12 @@ public class Scalar extends AbstractOpenApiSchema {
return;
}
// check if the actual instance is of the type `UUID`
if (value.getActualInstance() instanceof UUID) {
JsonElement element = adapterUUID.toJsonTree((UUID)value.getActualInstance());
elementAdapter.write(out, element);
return;
}
// check if the actual instance is of the type `String`
if (value.getActualInstance() instanceof String) {
JsonPrimitive primitive = adapterString.toJsonTree((String)value.getActualInstance()).getAsJsonPrimitive();
@@ -93,7 +101,7 @@ public class Scalar extends AbstractOpenApiSchema {
elementAdapter.write(out, primitive);
return;
}
throw new IOException("Failed to serialize as the type doesn't match oneOf schemas: BigDecimal, Boolean, String");
throw new IOException("Failed to serialize as the type doesn't match oneOf schemas: BigDecimal, Boolean, String, UUID");
}
@Override
@@ -105,6 +113,18 @@ public class Scalar extends AbstractOpenApiSchema {
ArrayList<String> errorMessages = new ArrayList<>();
TypeAdapter actualAdapter = elementAdapter;
// deserialize UUID
try {
// validate the JSON object to see if any exception is thrown
UUID.fromString(jsonElement.getAsString());
actualAdapter = adapterUUID;
match++;
log.log(Level.FINER, "Input data matches schema 'UUID'");
} catch (Exception e) {
// deserialization failed, continue
errorMessages.add(String.format("Deserialization for UUID failed with `%s`.", e.getMessage()));
log.log(Level.FINER, "Input data does not match schema 'UUID'", e);
}
// deserialize String
try {
// validate the JSON object to see if any exception is thrown
@@ -173,6 +193,7 @@ public class Scalar extends AbstractOpenApiSchema {
}
static {
schemas.put("UUID", UUID.class);
schemas.put("String", String.class);
schemas.put("BigDecimal", BigDecimal.class);
schemas.put("Boolean", Boolean.class);
@@ -186,12 +207,17 @@ public class Scalar extends AbstractOpenApiSchema {
/**
* Set the instance that matches the oneOf child schema, check
* the instance parameter is valid against the oneOf child schemas:
* BigDecimal, Boolean, String
* BigDecimal, Boolean, String, UUID
*
* It could be an instance of the 'oneOf' schemas.
*/
@Override
public void setActualInstance(Object instance) {
if (instance instanceof UUID) {
super.setActualInstance(instance);
return;
}
if (instance instanceof String) {
super.setActualInstance(instance);
return;
@@ -207,14 +233,14 @@ public class Scalar extends AbstractOpenApiSchema {
return;
}
throw new RuntimeException("Invalid instance type. Must be BigDecimal, Boolean, String");
throw new RuntimeException("Invalid instance type. Must be BigDecimal, Boolean, String, UUID");
}
/**
* Get the actual instance, which can be the following:
* BigDecimal, Boolean, String
* BigDecimal, Boolean, String, UUID
*
* @return The actual instance (BigDecimal, Boolean, String)
* @return The actual instance (BigDecimal, Boolean, String, UUID)
*/
@SuppressWarnings("unchecked")
@Override
@@ -222,6 +248,17 @@ public class Scalar extends AbstractOpenApiSchema {
return super.getActualInstance();
}
/**
* Get the actual instance of `UUID`. If the actual instance is not `UUID`,
* the ClassCastException will be thrown.
*
* @return The actual instance of `UUID`
* @throws ClassCastException if the instance is not `UUID`
*/
public UUID getUUID() throws ClassCastException {
return (UUID)super.getActualInstance();
}
/**
* Get the actual instance of `String`. If the actual instance is not `String`,
* the ClassCastException will be thrown.
@@ -265,6 +302,14 @@ public class Scalar extends AbstractOpenApiSchema {
// validate oneOf schemas one by one
int validCount = 0;
ArrayList<String> errorMessages = new ArrayList<>();
// validate the json string with UUID
try {
UUID.fromString(jsonElement.getAsString());
validCount++;
} catch (Exception e) {
errorMessages.add(String.format("Deserialization for UUID failed with `%s`.", e.getMessage()));
// continue to the next one
}
// validate the json string with String
try {
if (!jsonElement.getAsJsonPrimitive().isString()) {
@@ -296,7 +341,7 @@ public class Scalar extends AbstractOpenApiSchema {
// continue to the next one
}
if (validCount != 1) {
throw new IOException(String.format("The JSON string is invalid for Scalar with oneOf schemas: BigDecimal, Boolean, String. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonElement.toString()));
throw new IOException(String.format("The JSON string is invalid for Scalar with oneOf schemas: BigDecimal, Boolean, String, UUID. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonElement.toString()));
}
}

View File

@@ -15,6 +15,7 @@ package org.openapitools.client.model;
import java.util.Objects;
import java.math.BigDecimal;
import java.util.UUID;
@@ -63,6 +64,7 @@ public class ScalarAnyOf extends AbstractOpenApiSchema {
return null; // this class only serializes 'ScalarAnyOf' and its subtypes
}
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
final TypeAdapter<UUID> adapterUUID = gson.getDelegateAdapter(this, TypeToken.get(UUID.class));
final TypeAdapter<String> adapterString = gson.getDelegateAdapter(this, TypeToken.get(String.class));
final TypeAdapter<BigDecimal> adapterBigDecimal = gson.getDelegateAdapter(this, TypeToken.get(BigDecimal.class));
final TypeAdapter<Boolean> adapterBoolean = gson.getDelegateAdapter(this, TypeToken.get(Boolean.class));
@@ -75,6 +77,12 @@ public class ScalarAnyOf extends AbstractOpenApiSchema {
return;
}
// check if the actual instance is of the type `UUID`
if (value.getActualInstance() instanceof UUID) {
JsonElement element = adapterUUID.toJsonTree((UUID)value.getActualInstance());
elementAdapter.write(out, element);
return;
}
// check if the actual instance is of the type `String`
if (value.getActualInstance() instanceof String) {
JsonPrimitive primitive = adapterString.toJsonTree((String)value.getActualInstance()).getAsJsonPrimitive();
@@ -93,7 +101,7 @@ public class ScalarAnyOf extends AbstractOpenApiSchema {
elementAdapter.write(out, primitive);
return;
}
throw new IOException("Failed to serialize as the type doesn't match anyOf schemas: BigDecimal, Boolean, String");
throw new IOException("Failed to serialize as the type doesn't match anyOf schemas: BigDecimal, Boolean, String, UUID");
}
@Override
@@ -104,6 +112,19 @@ public class ScalarAnyOf extends AbstractOpenApiSchema {
ArrayList<String> errorMessages = new ArrayList<>();
TypeAdapter actualAdapter = elementAdapter;
// deserialize UUID
try {
// validate the JSON object to see if any exception is thrown
UUID.fromString(jsonElement.getAsString());
actualAdapter = adapterUUID;
ScalarAnyOf ret = new ScalarAnyOf();
ret.setActualInstance(actualAdapter.fromJsonTree(jsonElement));
return ret;
} catch (Exception e) {
// deserialization failed, continue
errorMessages.add(String.format("Deserialization for UUID failed with `%s`.", e.getMessage()));
log.log(Level.FINER, "Input data does not match schema 'UUID'", e);
}
// deserialize String
try {
// validate the JSON object to see if any exception is thrown
@@ -169,6 +190,7 @@ public class ScalarAnyOf extends AbstractOpenApiSchema {
}
static {
schemas.put("UUID", UUID.class);
schemas.put("String", String.class);
schemas.put("BigDecimal", BigDecimal.class);
schemas.put("Boolean", Boolean.class);
@@ -182,12 +204,17 @@ public class ScalarAnyOf extends AbstractOpenApiSchema {
/**
* Set the instance that matches the anyOf child schema, check
* the instance parameter is valid against the anyOf child schemas:
* BigDecimal, Boolean, String
* BigDecimal, Boolean, String, UUID
*
* It could be an instance of the 'anyOf' schemas.
*/
@Override
public void setActualInstance(Object instance) {
if (instance instanceof UUID) {
super.setActualInstance(instance);
return;
}
if (instance instanceof String) {
super.setActualInstance(instance);
return;
@@ -203,14 +230,14 @@ public class ScalarAnyOf extends AbstractOpenApiSchema {
return;
}
throw new RuntimeException("Invalid instance type. Must be BigDecimal, Boolean, String");
throw new RuntimeException("Invalid instance type. Must be BigDecimal, Boolean, String, UUID");
}
/**
* Get the actual instance, which can be the following:
* BigDecimal, Boolean, String
* BigDecimal, Boolean, String, UUID
*
* @return The actual instance (BigDecimal, Boolean, String)
* @return The actual instance (BigDecimal, Boolean, String, UUID)
*/
@SuppressWarnings("unchecked")
@Override
@@ -218,6 +245,17 @@ public class ScalarAnyOf extends AbstractOpenApiSchema {
return super.getActualInstance();
}
/**
* Get the actual instance of `UUID`. If the actual instance is not `UUID`,
* the ClassCastException will be thrown.
*
* @return The actual instance of `UUID`
* @throws ClassCastException if the instance is not `UUID`
*/
public UUID getUUID() throws ClassCastException {
return (UUID)super.getActualInstance();
}
/**
* Get the actual instance of `String`. If the actual instance is not `String`,
* the ClassCastException will be thrown.
@@ -260,6 +298,14 @@ public class ScalarAnyOf extends AbstractOpenApiSchema {
public static void validateJsonElement(JsonElement jsonElement) throws IOException {
// validate anyOf schemas one by one
ArrayList<String> errorMessages = new ArrayList<>();
// validate the json string with UUID
try {
UUID.fromString(jsonElement.getAsString());
return;
} catch (Exception e) {
errorMessages.add(String.format("Deserialization for UUID failed with `%s`.", e.getMessage()));
// continue to the next one
}
// validate the json string with String
try {
if (!jsonElement.getAsJsonPrimitive().isString()) {
@@ -290,7 +336,7 @@ public class ScalarAnyOf extends AbstractOpenApiSchema {
errorMessages.add(String.format("Deserialization for Boolean failed with `%s`.", e.getMessage()));
// continue to the next one
}
throw new IOException(String.format("The JSON string is invalid for ScalarAnyOf with anyOf schemas: BigDecimal, Boolean, String. no class match the result, expected at least 1. Detailed failure message for anyOf schemas: %s. JSON: %s", errorMessages, jsonElement.toString()));
throw new IOException(String.format("The JSON string is invalid for ScalarAnyOf with anyOf schemas: BigDecimal, Boolean, String, UUID. no class match the result, expected at least 1. Detailed failure message for anyOf schemas: %s. JSON: %s", errorMessages, jsonElement.toString()));
}
/**