Skip to content

Commit

Permalink
[java][okhttp-gson-nextgen] better oneOf implementation (#11146)
Browse files Browse the repository at this point in the history
* add validJsonObject method

* add check for null

* fix list model generation

* fix optional fields validation

* add tests

* fix variable naming

* update tests

* add fromJson in oneOf, add tests

* convert JSON to static

* remove trailing space

* add fromString methods to all models

* add toJson, fix anyOf template

* remove workarounds

* undo changes to tests

* skip file schema test

* add new file
  • Loading branch information
wing328 authored Dec 18, 2021
1 parent d65bf8d commit b72eba9
Show file tree
Hide file tree
Showing 247 changed files with 16,330 additions and 1,135 deletions.
3 changes: 1 addition & 2 deletions bin/configs/java-okhttp-gson-nextgen.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
generatorName: java
outputDir: samples/client/petstore/java/okhttp-gson-nextgen
library: okhttp-gson-nextgen
#inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml
inputSpec: modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-with-http-signature-okhttp-gson.yaml
inputSpec: modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-with-http-signature-okhttp-gson-nextgen.yaml
templateDir: modules/openapi-generator/src/main/resources/Java
additionalProperties:
artifactId: petstore-okhttp-gson-nextgen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,19 @@ import java.util.HashMap;
* backward-compatibility
*/
public class JSON {
private Gson gson;
private boolean isLenientOnJson = false;
private DateTypeAdapter dateTypeAdapter = new DateTypeAdapter();
private SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter();
private static Gson gson;
private static boolean isLenientOnJson = false;
private static DateTypeAdapter dateTypeAdapter = new DateTypeAdapter();
private static SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter();
{{#joda}}
private DateTimeTypeAdapter dateTimeTypeAdapter = new DateTimeTypeAdapter();
private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter();
private static DateTimeTypeAdapter dateTimeTypeAdapter = new DateTimeTypeAdapter();
private static LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter();
{{/joda}}
{{#jsr310}}
private OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter();
private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter();
private static OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter();
private static LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter();
{{/jsr310}}
private ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter();
private static ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter();

@SuppressWarnings("unchecked")
public static GsonBuilder createGson() {
Expand Down Expand Up @@ -116,7 +116,7 @@ public class JSON {
return clazz;
}

public JSON() {
{
gson = createGson()
.registerTypeAdapter(Date.class, dateTypeAdapter)
.registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter)
Expand Down Expand Up @@ -146,7 +146,7 @@ public class JSON {
*
* @return Gson
*/
public Gson getGson() {
public static Gson getGson() {
return gson;
}

Expand All @@ -155,11 +155,11 @@ public class JSON {
*
* @param gson Gson
*/
public void setGson(Gson gson) {
this.gson = gson;
public static void setGson(Gson gson) {
JSON.gson = gson;
}

public void setLenientOnJson(boolean lenientOnJson) {
public static void setLenientOnJson(boolean lenientOnJson) {
isLenientOnJson = lenientOnJson;
}

Expand All @@ -169,7 +169,7 @@ public class JSON {
* @param obj Object
* @return String representation of the JSON
*/
public String serialize(Object obj) {
public static String serialize(Object obj) {
return gson.toJson(obj);
}

Expand All @@ -182,7 +182,7 @@ public class JSON {
* @return The deserialized Java object
*/
@SuppressWarnings("unchecked")
public <T> T deserialize(String body, Type returnType) {
public static <T> T deserialize(String body, Type returnType) {
try {
if (isLenientOnJson) {
JsonReader jsonReader = new JsonReader(new StringReader(body));
Expand All @@ -206,7 +206,7 @@ public class JSON {
/**
* Gson TypeAdapter for Byte Array type
*/
public class ByteArrayAdapter extends TypeAdapter<byte[]> {
public static class ByteArrayAdapter extends TypeAdapter<byte[]> {
@Override
public void write(JsonWriter out, byte[] value) throws IOException {
Expand Down Expand Up @@ -235,7 +235,7 @@ public class JSON {
/**
* Gson TypeAdapter for Joda DateTime type
*/
public class DateTimeTypeAdapter extends TypeAdapter<DateTime> {
public static class DateTimeTypeAdapter extends TypeAdapter<DateTime> {
private DateTimeFormatter formatter;
Expand Down Expand Up @@ -278,7 +278,7 @@ public class JSON {
/**
* Gson TypeAdapter for Joda LocalDate type
*/
public class LocalDateTypeAdapter extends TypeAdapter<LocalDate> {
public static class LocalDateTypeAdapter extends TypeAdapter<LocalDate> {
private DateTimeFormatter formatter;
Expand Down Expand Up @@ -316,11 +316,11 @@ public class JSON {
}
}

public void setDateTimeFormat(DateTimeFormatter dateFormat) {
public static void setDateTimeFormat(DateTimeFormatter dateFormat) {
dateTimeTypeAdapter.setFormat(dateFormat);
}

public void setLocalDateFormat(DateTimeFormatter dateFormat) {
public static void setLocalDateFormat(DateTimeFormatter dateFormat) {
localDateTypeAdapter.setFormat(dateFormat);
}

Expand All @@ -329,7 +329,7 @@ public class JSON {
/**
* Gson TypeAdapter for JSR310 OffsetDateTime type
*/
public class OffsetDateTimeTypeAdapter extends TypeAdapter<OffsetDateTime> {
public static class OffsetDateTimeTypeAdapter extends TypeAdapter<OffsetDateTime> {
private DateTimeFormatter formatter;
Expand Down Expand Up @@ -373,7 +373,7 @@ public class JSON {
/**
* Gson TypeAdapter for JSR310 LocalDate type
*/
public class LocalDateTypeAdapter extends TypeAdapter<LocalDate> {
public static class LocalDateTypeAdapter extends TypeAdapter<LocalDate> {
private DateTimeFormatter formatter;
Expand Down Expand Up @@ -411,11 +411,11 @@ public class JSON {
}
}

public void setOffsetDateTimeFormat(DateTimeFormatter dateFormat) {
public static void setOffsetDateTimeFormat(DateTimeFormatter dateFormat) {
offsetDateTimeTypeAdapter.setFormat(dateFormat);
}

public void setLocalDateFormat(DateTimeFormatter dateFormat) {
public static void setLocalDateFormat(DateTimeFormatter dateFormat) {
localDateTypeAdapter.setFormat(dateFormat);
}

Expand All @@ -425,7 +425,7 @@ public class JSON {
* If the dateFormat is null, a simple "yyyy-MM-dd" format will be used
* (more efficient than SimpleDateFormat).
*/
public class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
public static class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
private DateFormat dateFormat;
Expand Down Expand Up @@ -478,7 +478,7 @@ public class JSON {
* Gson TypeAdapter for java.util.Date type
* If the dateFormat is null, ISO8601Utils will be used.
*/
public class DateTypeAdapter extends TypeAdapter<Date> {
public static class DateTypeAdapter extends TypeAdapter<Date> {
private DateFormat dateFormat;
Expand Down Expand Up @@ -531,11 +531,11 @@ public class JSON {
}
}

public void setDateFormat(DateFormat dateFormat) {
public static void setDateFormat(DateFormat dateFormat) {
dateTypeAdapter.setFormat(dateFormat);
}

public void setSqlDateFormat(DateFormat dateFormat) {
public static void setSqlDateFormat(DateFormat dateFormat) {
sqlDateTypeAdapter.setFormat(dateFormat);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,22 +90,23 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im

{{/discriminator}}
{{/useOneOfDiscriminatorLookup}}

{{#anyOf}}
// deserialize {{{.}}}
try {
deserialized = adapter{{.}}.fromJsonTree(jsonObject);
// validate the JSON object to see if any excpetion is thrown
{{.}}.validateJsonObject(jsonObject);
log.log(Level.FINER, "Input data matches schema '{{{.}}}'");
{{classname}} ret = new {{classname}}();
ret.setActualInstance(deserialized);
ret.setActualInstance(adapter{{.}}.fromJsonTree(jsonObject));
return ret;
} catch (Exception e) {
// deserialization failed, continue
log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e);
}

{{/anyOf}}
throw new IOException(String.format("Failed deserialization for {{classname}} as data doesn't match anyOf schmeas: {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}. JSON: %s", jsonObject.toString()));

throw new IOException(String.format("Failed deserialization for {{classname}}: no class matched. JSON: %s", jsonObject.toString()));
}
}.nullSafe();
}
Expand Down Expand Up @@ -188,4 +189,48 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im
}

{{/anyOf}}

/**
* Validates the JSON Object and throws an exception if issues found
*
* @param jsonObj JSON Object
* @throws IOException if the JSON Object is invalid with respect to {{classname}}
*/
public static void validateJsonObject(JsonObject jsonObj) throws IOException {
// validate anyOf schemas one by one
int validCount = 0;
{{#anyOf}}
// validate the json string with {{{.}}}
try {
{{{.}}}.validateJsonObject(jsonObj);
return; // return earlier as at least one schema is valid with respect to the Json object
//validCount++;
} catch (Exception e) {
// continue to the next one
}
{{/anyOf}}
if (validCount == 0) {
throw new IOException(String.format("The JSON string is invalid for {{classname}} with anyOf schemas: {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}. JSON: %s", jsonObj.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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,14 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im
{{/discriminator}}
{{/useOneOfDiscriminatorLookup}}
int match = 0;
TypeAdapter actualAdapter = elementAdapter;

{{#oneOf}}
// deserialize {{{.}}}
try {
deserialized = adapter{{.}}.fromJsonTree(jsonObject);
// validate the JSON object to see if any excpetion is thrown
{{.}}.validateJsonObject(jsonObject);
actualAdapter = adapter{{.}};
match++;
log.log(Level.FINER, "Input data matches schema '{{{.}}}'");
} catch (Exception e) {
Expand All @@ -106,7 +109,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im
{{/oneOf}}
if (match == 1) {
{{classname}} ret = new {{classname}}();
ret.setActualInstance(deserialized);
ret.setActualInstance(actualAdapter.fromJsonTree(jsonObject));
return ret;
}

Expand Down Expand Up @@ -193,4 +196,47 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im
}

{{/oneOf}}

/**
* Validates the JSON Object and throws an exception if issues found
*
* @param jsonObj JSON Object
* @throws IOException if the JSON Object is invalid with respect to {{classname}}
*/
public static void validateJsonObject(JsonObject jsonObj) throws IOException {
// validate oneOf schemas one by one
int validCount = 0;
{{#oneOf}}
// validate the json string with {{{.}}}
try {
{{{.}}}.validateJsonObject(jsonObj);
validCount++;
} catch (Exception e) {
// continue to the next one
}
{{/oneOf}}
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. JSON: %s", validCount, jsonObj.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);
}
}
Loading

0 comments on commit b72eba9

Please sign in to comment.