Skip to content

Commit

Permalink
[Java][okhttp-gson] validateJsonElement does not validate enum values (
Browse files Browse the repository at this point in the history
…#16865)

* validate enum properties in validateJsonElement

* regenerate samples

* add test for enum validation in okhttp-gson models
  • Loading branch information
ctreatma authored Nov 8, 2023
1 parent 291ce35 commit 166ebc5
Show file tree
Hide file tree
Showing 54 changed files with 761 additions and 1 deletion.
2 changes: 1 addition & 1 deletion bin/utils/test_file_list.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
- filename: "samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/ClientTest.java"
sha256: db505f7801fef62c13a08a8e9ca1fc4c5c947ab46b46f12943139d353feacf17
- filename: "samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/JSONTest.java"
sha256: 3371236d615e7fb79ed87d00c9fc486c31c379195a658781ac9440f0e3228d62
sha256: 6db714e9744c150c8982c3cb18e4f37a9c1ecd8f72f6d58943986e781ab4a344
- filename: "samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/api/PetApiTest.java"
sha256: 0d64cdc11809a7b5b952ccdad2bd91bd0045b3894d6fabf3e368fa0be12b8217
- filename: "samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/model/PetTest.java"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
{{#jackson}}
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
{{/jackson}}
{{#gson}}
import java.io.IOException;
import com.google.gson.TypeAdapter;
import com.google.gson.JsonElement;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
{{/gson}}

/**
* {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}
*/
{{#gson}}
@JsonAdapter({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class)
{{/gson}}
{{#jsonb}}
@JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class)
@JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class)
{{/jsonb}}
{{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} {
{{#allowableValues}}{{#enumVars}}
{{#enumDescription}}
/**
* {{.}}
*/
{{/enumDescription}}
{{#withXml}}
@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}})
{{/withXml}}
{{{name}}}({{{value}}}){{^-last}},
{{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}

private {{{dataType}}} value;

{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) {
this.value = value;
}

{{#jackson}}
@JsonValue
{{/jackson}}
public {{{dataType}}} getValue() {
return value;
}

@Override
public String toString() {
return String.valueOf(value);
}

{{#jackson}}
@JsonCreator
{{/jackson}}
public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) {
for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
if (b.value.{{^isString}}equals{{/isString}}{{#isString}}{{#useEnumCaseInsensitive}}equalsIgnoreCase{{/useEnumCaseInsensitive}}{{^useEnumCaseInsensitive}}equals{{/useEnumCaseInsensitive}}{{/isString}}(value)) {
return b;
}
}
{{#isNullable}}return null;{{/isNullable}}{{^isNullable}}{{#enumUnknownDefaultCase}}{{#allowableValues}}{{#enumVars}}{{#-last}}return {{{name}}};{{/-last}}{{/enumVars}}{{/allowableValues}}{{/enumUnknownDefaultCase}}{{^enumUnknownDefaultCase}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/enumUnknownDefaultCase}}{{/isNullable}}
}
{{#gson}}

public static class Adapter extends TypeAdapter<{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> {
@Override
public void write(final JsonWriter jsonWriter, final {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException {
jsonWriter.value(enumeration.getValue());
}

@Override
public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}{{/isNumber}};
return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}

public static void validateJsonElement(JsonElement jsonElement) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonElement.{{#isNumber}}getAsString(){{/isNumber}}{{#isInteger}}getAsInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}getAs{{{dataType}}}(){{/isInteger}}{{/isNumber}};
{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
{{/gson}}
{{#jsonb}}

public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> {
@Override
public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) {
for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
if (String.valueOf(b.value).equals(parser.getString())) {
return b;
}
}
{{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}}
}
}

public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> {
@Override
public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) {
generator.write(obj.value);
}
}
{{/jsonb}}
{{#supportUrlQuery}}

/**
* Convert the instance into URL query string.
*
* @param prefix prefix of the query string
* @return URL query string
*/
public String toUrlQueryString(String prefix) {
if (prefix == null) {
prefix = "";
}

return String.format("%s=%s", prefix, this.toString());
}
{{/supportUrlQuery}}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
* {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}
*/
{{#gson}}
@JsonAdapter({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.Adapter.class)
{{/gson}}
{{#jsonb}}
@JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class)
@JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class)
{{/jsonb}}
{{#withXml}}
@XmlType(name="{{datatypeWithEnum}}")
@XmlEnum({{dataType}}.class)
{{/withXml}}
{{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} {
{{#allowableValues}}
{{#enumVars}}
{{#enumDescription}}
/**
* {{.}}
*/
{{/enumDescription}}
{{#withXml}}
@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}})
{{/withXml}}
{{{name}}}({{{value}}}){{^-last}},
{{/-last}}{{#-last}};{{/-last}}
{{/enumVars}}
{{/allowableValues}}

private {{{dataType}}} value;

{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{dataType}}} value) {
this.value = value;
}

{{#jackson}}
@JsonValue
{{/jackson}}
public {{{dataType}}} getValue() {
return value;
}

@Override
public String toString() {
return String.valueOf(value);
}

{{#jackson}}
@JsonCreator
{{/jackson}}
public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) {
for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
if (b.value.{{^isString}}equals{{/isString}}{{#isString}}{{#useEnumCaseInsensitive}}equalsIgnoreCase{{/useEnumCaseInsensitive}}{{^useEnumCaseInsensitive}}equals{{/useEnumCaseInsensitive}}{{/isString}}(value)) {
return b;
}
}
{{#isNullable}}return null;{{/isNullable}}{{^isNullable}}{{#enumUnknownDefaultCase}}{{#allowableValues}}{{#enumVars}}{{#-last}}return {{{name}}};{{/-last}}{{/enumVars}}{{/allowableValues}}{{/enumUnknownDefaultCase}}{{^enumUnknownDefaultCase}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/enumUnknownDefaultCase}}{{/isNullable}}
}
{{#gson}}

public static class Adapter extends TypeAdapter<{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}> {
@Override
public void write(final JsonWriter jsonWriter, final {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} enumeration) throws IOException {
jsonWriter.value(enumeration.getValue());
}

@Override
public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}} jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isInteger}}{{/isNumber}};
return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}

public static void validateJsonElement(JsonElement jsonElement) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonElement.{{#isNumber}}getAsString(){{/isNumber}}{{#isInteger}}getAsInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}getAs{{{dataType}}}(){{/isInteger}}{{/isNumber}};
{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
{{/gson}}
{{#jsonb}}
public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> {
@Override
public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) {
for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
if (String.valueOf(b.value).equals(parser.getString())) {
return b;
}
}
{{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}}
}
}

public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> {
@Override
public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) {
generator.write(obj.value);
}
}
{{/jsonb}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,30 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
}
{{/required}}
{{/isModel}}
{{#isEnum}}
{{#required}}
// validate the required field `{{{baseName}}}`
{{{datatypeWithEnum}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
{{/required}}
{{^required}}
// validate the optional field `{{{baseName}}}`
if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
{{{datatypeWithEnum}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
}
{{/required}}
{{/isEnum}}
{{#isEnumRef}}
{{#required}}
// validate the required field `{{{baseName}}}`
{{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
{{/required}}
{{^required}}
// validate the optional field `{{{baseName}}}`
if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
{{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
}
{{/required}}
{{/isEnumRef}}
{{/isContainer}}
{{/vars}}
{{/discriminator}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ public ArrayStringEnumDefaultEnum read(final JsonReader jsonReader) throws IOExc
return ArrayStringEnumDefaultEnum.fromValue(value);
}
}

public static void validateJsonElement(JsonElement jsonElement) throws IOException {
String value = jsonElement.getAsString();
ArrayStringEnumDefaultEnum.fromValue(value);
}
}

public static final String SERIALIZED_NAME_ARRAY_STRING_ENUM_DEFAULT = "array_string_enum_default";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ public StatusEnum read(final JsonReader jsonReader) throws IOException {
return StatusEnum.fromValue(value);
}
}

public static void validateJsonElement(JsonElement jsonElement) throws IOException {
String value = jsonElement.getAsString();
StatusEnum.fromValue(value);
}
}

public static final String SERIALIZED_NAME_STATUS = "status";
Expand Down Expand Up @@ -399,6 +404,10 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti
if ((jsonObj.get("status") != null && !jsonObj.get("status").isJsonNull()) && !jsonObj.get("status").isJsonPrimitive()) {
throw new IllegalArgumentException(String.format("Expected the field `status` to be a primitive type in the JSON string but got `%s`", jsonObj.get("status").toString()));
}
// validate the optional field `status`
if (jsonObj.get("status") != null && !jsonObj.get("status").isJsonNull()) {
StatusEnum.validateJsonElement(jsonObj.get("status"));
}
}

public static class CustomTypeAdapterFactory implements TypeAdapterFactory {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ public OutcomesEnum read(final JsonReader jsonReader) throws IOException {
return OutcomesEnum.fromValue(value);
}
}

public static void validateJsonElement(JsonElement jsonElement) throws IOException {
String value = jsonElement.getAsString();
OutcomesEnum.fromValue(value);
}
}

public static final String SERIALIZED_NAME_OUTCOMES = "outcomes";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.io.IOException;
import com.google.gson.TypeAdapter;
import com.google.gson.JsonElement;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
Expand Down Expand Up @@ -70,5 +71,10 @@ public StringEnumRef read(final JsonReader jsonReader) throws IOException {
return StringEnumRef.fromValue(value);
}
}

public static void validateJsonElement(JsonElement jsonElement) throws IOException {
String value = jsonElement.getAsString();
StringEnumRef.fromValue(value);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ public TypeEnum read(final JsonReader jsonReader) throws IOException {
return TypeEnum.fromValue(value);
}
}

public static void validateJsonElement(JsonElement jsonElement) throws IOException {
String value = jsonElement.getAsString();
TypeEnum.fromValue(value);
}
}

public static final String SERIALIZED_NAME_$_TYPE = "$_type";
Expand Down Expand Up @@ -314,6 +319,10 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti
if ((jsonObj.get("$_type") != null && !jsonObj.get("$_type").isJsonNull()) && !jsonObj.get("$_type").isJsonPrimitive()) {
throw new IllegalArgumentException(String.format("Expected the field `$_type` to be a primitive type in the JSON string but got `%s`", jsonObj.get("$_type").toString()));
}
// validate the optional field `$_type`
if (jsonObj.get("$_type") != null && !jsonObj.get("$_type").isJsonNull()) {
TypeEnum.validateJsonElement(jsonObj.get("$_type"));
}
if ((jsonObj.get("name") != null && !jsonObj.get("name").isJsonNull()) && !jsonObj.get("name").isJsonPrimitive()) {
throw new IllegalArgumentException(String.format("Expected the field `name` to be a primitive type in the JSON string but got `%s`", jsonObj.get("name").toString()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ public StatusEnum read(final JsonReader jsonReader) throws IOException {
return StatusEnum.fromValue(value);
}
}

public static void validateJsonElement(JsonElement jsonElement) throws IOException {
String value = jsonElement.getAsString();
StatusEnum.fromValue(value);
}
}

public static final String SERIALIZED_NAME_STATUS = "status";
Expand Down Expand Up @@ -382,6 +387,10 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti
if ((jsonObj.get("status") != null && !jsonObj.get("status").isJsonNull()) && !jsonObj.get("status").isJsonPrimitive()) {
throw new IllegalArgumentException(String.format("Expected the field `status` to be a primitive type in the JSON string but got `%s`", jsonObj.get("status").toString()));
}
// validate the optional field `status`
if (jsonObj.get("status") != null && !jsonObj.get("status").isJsonNull()) {
StatusEnum.validateJsonElement(jsonObj.get("status"));
}
}

public static class CustomTypeAdapterFactory implements TypeAdapterFactory {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ public StatusEnum read(final JsonReader jsonReader) throws IOException {
return StatusEnum.fromValue(value);
}
}

public static void validateJsonElement(JsonElement jsonElement) throws IOException {
String value = jsonElement.getAsString();
StatusEnum.fromValue(value);
}
}

public static final String SERIALIZED_NAME_STATUS = "status";
Expand Down Expand Up @@ -442,6 +447,10 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti
if ((jsonObj.get("status") != null && !jsonObj.get("status").isJsonNull()) && !jsonObj.get("status").isJsonPrimitive()) {
throw new IllegalArgumentException(String.format("Expected the field `status` to be a primitive type in the JSON string but got `%s`", jsonObj.get("status").toString()));
}
// validate the optional field `status`
if (jsonObj.get("status") != null && !jsonObj.get("status").isJsonNull()) {
StatusEnum.validateJsonElement(jsonObj.get("status"));
}
}

public static class CustomTypeAdapterFactory implements TypeAdapterFactory {
Expand Down
Loading

0 comments on commit 166ebc5

Please sign in to comment.