From 68360cab9297c8f0241320de9165352de7154231 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 10 May 2022 17:16:02 +0800 Subject: [PATCH] better error messages for oneOf in java okhttp-gson (#12311) --- .../Java/libraries/okhttp-gson/oneof_model.mustache | 8 ++++++-- .../java/org/openapitools/client/model/Fruit.java | 10 ++++++++-- .../java/org/openapitools/client/model/FruitReq.java | 10 ++++++++-- .../java/org/openapitools/client/model/Mammal.java | 12 ++++++++++-- .../org/openapitools/client/model/NullableShape.java | 10 ++++++++-- .../main/java/org/openapitools/client/model/Pig.java | 10 ++++++++-- .../org/openapitools/client/model/Quadrilateral.java | 10 ++++++++-- .../java/org/openapitools/client/model/Shape.java | 10 ++++++++-- .../org/openapitools/client/model/ShapeOrNull.java | 10 ++++++++-- .../java/org/openapitools/client/model/Triangle.java | 12 ++++++++++-- .../test/java/org/openapitools/client/JSONTest.java | 6 +++--- 11 files changed, 85 insertions(+), 23 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/oneof_model.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/oneof_model.mustache index 1e7748d0ed2a..9b94b365f4c3 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/oneof_model.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/oneof_model.mustache @@ -95,6 +95,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im {{/discriminator}} {{/useOneOfDiscriminatorLookup}} int match = 0; + ArrayList errorMessages = new ArrayList<>(); TypeAdapter actualAdapter = elementAdapter; {{#oneOf}} @@ -107,6 +108,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im 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); } @@ -117,7 +119,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im return ret; } - throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1. JSON: %s", match, jsonObject.toString())); + 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, jsonObject.toString())); } }.nullSafe(); } @@ -210,17 +212,19 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im public static void validateJsonObject(JsonObject jsonObj) throws IOException { // validate oneOf schemas one by one int validCount = 0; + ArrayList errorMessages = new ArrayList<>(); {{#oneOf}} // validate the json string with {{{.}}} try { {{{.}}}.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for {{{.}}} failed with `%s`.", e.getMessage())); // 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())); + 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, jsonObj.toString())); } } diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Fruit.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Fruit.java index b3f039428acf..4ef91c173457 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Fruit.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Fruit.java @@ -106,6 +106,7 @@ public Fruit read(JsonReader in) throws IOException { JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject(); int match = 0; + ArrayList errorMessages = new ArrayList<>(); TypeAdapter actualAdapter = elementAdapter; // deserialize Apple @@ -117,6 +118,7 @@ public Fruit read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'Apple'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for Apple failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'Apple'", e); } @@ -129,6 +131,7 @@ public Fruit read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'Banana'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for Banana failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'Banana'", e); } @@ -138,7 +141,7 @@ public Fruit read(JsonReader in) throws IOException { return ret; } - throw new IOException(String.format("Failed deserialization for Fruit: %d classes match result, expected 1. JSON: %s", match, jsonObject.toString())); + throw new IOException(String.format("Failed deserialization for Fruit: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonObject.toString())); } }.nullSafe(); } @@ -239,11 +242,13 @@ public Banana getBanana() throws ClassCastException { public static void validateJsonObject(JsonObject jsonObj) throws IOException { // validate oneOf schemas one by one int validCount = 0; + ArrayList errorMessages = new ArrayList<>(); // validate the json string with Apple try { Apple.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for Apple failed with `%s`.", e.getMessage())); // continue to the next one } // validate the json string with Banana @@ -251,10 +256,11 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { Banana.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for Banana failed with `%s`.", e.getMessage())); // continue to the next one } if (validCount != 1) { - throw new IOException(String.format("The JSON string is invalid for Fruit with oneOf schemas: Apple, Banana. %d class(es) match the result, expected 1. JSON: %s", validCount, jsonObj.toString())); + throw new IOException(String.format("The JSON string is invalid for Fruit with oneOf schemas: Apple, Banana. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonObj.toString())); } } diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/FruitReq.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/FruitReq.java index 546d0cdc7173..67f8741b448e 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/FruitReq.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/FruitReq.java @@ -106,6 +106,7 @@ public FruitReq read(JsonReader in) throws IOException { JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject(); int match = 0; + ArrayList errorMessages = new ArrayList<>(); TypeAdapter actualAdapter = elementAdapter; // deserialize AppleReq @@ -117,6 +118,7 @@ public FruitReq read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'AppleReq'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for AppleReq failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'AppleReq'", e); } @@ -129,6 +131,7 @@ public FruitReq read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'BananaReq'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for BananaReq failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'BananaReq'", e); } @@ -138,7 +141,7 @@ public FruitReq read(JsonReader in) throws IOException { return ret; } - throw new IOException(String.format("Failed deserialization for FruitReq: %d classes match result, expected 1. JSON: %s", match, jsonObject.toString())); + throw new IOException(String.format("Failed deserialization for FruitReq: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonObject.toString())); } }.nullSafe(); } @@ -244,11 +247,13 @@ public BananaReq getBananaReq() throws ClassCastException { public static void validateJsonObject(JsonObject jsonObj) throws IOException { // validate oneOf schemas one by one int validCount = 0; + ArrayList errorMessages = new ArrayList<>(); // validate the json string with AppleReq try { AppleReq.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for AppleReq failed with `%s`.", e.getMessage())); // continue to the next one } // validate the json string with BananaReq @@ -256,10 +261,11 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { BananaReq.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for BananaReq failed with `%s`.", e.getMessage())); // continue to the next one } if (validCount != 1) { - throw new IOException(String.format("The JSON string is invalid for FruitReq with oneOf schemas: AppleReq, BananaReq. %d class(es) match the result, expected 1. JSON: %s", validCount, jsonObj.toString())); + throw new IOException(String.format("The JSON string is invalid for FruitReq with oneOf schemas: AppleReq, BananaReq. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonObj.toString())); } } diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Mammal.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Mammal.java index fe4771cc4cf2..9e03b4034202 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Mammal.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Mammal.java @@ -138,6 +138,7 @@ public Mammal read(JsonReader in) throws IOException { } int match = 0; + ArrayList errorMessages = new ArrayList<>(); TypeAdapter actualAdapter = elementAdapter; // deserialize Pig @@ -149,6 +150,7 @@ public Mammal read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'Pig'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for Pig failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'Pig'", e); } @@ -161,6 +163,7 @@ public Mammal read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'Whale'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for Whale failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'Whale'", e); } @@ -173,6 +176,7 @@ public Mammal read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'Zebra'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for Zebra failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'Zebra'", e); } @@ -182,7 +186,7 @@ public Mammal read(JsonReader in) throws IOException { return ret; } - throw new IOException(String.format("Failed deserialization for Mammal: %d classes match result, expected 1. JSON: %s", match, jsonObject.toString())); + throw new IOException(String.format("Failed deserialization for Mammal: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonObject.toString())); } }.nullSafe(); } @@ -306,11 +310,13 @@ public Zebra getZebra() throws ClassCastException { public static void validateJsonObject(JsonObject jsonObj) throws IOException { // validate oneOf schemas one by one int validCount = 0; + ArrayList errorMessages = new ArrayList<>(); // validate the json string with Pig try { Pig.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for Pig failed with `%s`.", e.getMessage())); // continue to the next one } // validate the json string with Whale @@ -318,6 +324,7 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { Whale.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for Whale failed with `%s`.", e.getMessage())); // continue to the next one } // validate the json string with Zebra @@ -325,10 +332,11 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { Zebra.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for Zebra failed with `%s`.", e.getMessage())); // continue to the next one } if (validCount != 1) { - throw new IOException(String.format("The JSON string is invalid for Mammal with oneOf schemas: Pig, Whale, Zebra. %d class(es) match the result, expected 1. JSON: %s", validCount, jsonObj.toString())); + throw new IOException(String.format("The JSON string is invalid for Mammal with oneOf schemas: Pig, Whale, Zebra. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonObj.toString())); } } diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/NullableShape.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/NullableShape.java index beb9bf6f6e40..2c56ae2d3534 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/NullableShape.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/NullableShape.java @@ -125,6 +125,7 @@ public NullableShape read(JsonReader in) throws IOException { } int match = 0; + ArrayList errorMessages = new ArrayList<>(); TypeAdapter actualAdapter = elementAdapter; // deserialize Quadrilateral @@ -136,6 +137,7 @@ public NullableShape read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'Quadrilateral'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for Quadrilateral failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'Quadrilateral'", e); } @@ -148,6 +150,7 @@ public NullableShape read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'Triangle'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for Triangle failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'Triangle'", e); } @@ -157,7 +160,7 @@ public NullableShape read(JsonReader in) throws IOException { return ret; } - throw new IOException(String.format("Failed deserialization for NullableShape: %d classes match result, expected 1. JSON: %s", match, jsonObject.toString())); + throw new IOException(String.format("Failed deserialization for NullableShape: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonObject.toString())); } }.nullSafe(); } @@ -263,11 +266,13 @@ public Triangle getTriangle() throws ClassCastException { public static void validateJsonObject(JsonObject jsonObj) throws IOException { // validate oneOf schemas one by one int validCount = 0; + ArrayList errorMessages = new ArrayList<>(); // validate the json string with Quadrilateral try { Quadrilateral.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for Quadrilateral failed with `%s`.", e.getMessage())); // continue to the next one } // validate the json string with Triangle @@ -275,10 +280,11 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { Triangle.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for Triangle failed with `%s`.", e.getMessage())); // continue to the next one } if (validCount != 1) { - throw new IOException(String.format("The JSON string is invalid for NullableShape with oneOf schemas: Quadrilateral, Triangle. %d class(es) match the result, expected 1. JSON: %s", validCount, jsonObj.toString())); + throw new IOException(String.format("The JSON string is invalid for NullableShape with oneOf schemas: Quadrilateral, Triangle. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonObj.toString())); } } diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Pig.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Pig.java index 54bbc3b6e183..81e3ad5c06bf 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Pig.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Pig.java @@ -125,6 +125,7 @@ public Pig read(JsonReader in) throws IOException { } int match = 0; + ArrayList errorMessages = new ArrayList<>(); TypeAdapter actualAdapter = elementAdapter; // deserialize BasquePig @@ -136,6 +137,7 @@ public Pig read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'BasquePig'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for BasquePig failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'BasquePig'", e); } @@ -148,6 +150,7 @@ public Pig read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'DanishPig'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for DanishPig failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'DanishPig'", e); } @@ -157,7 +160,7 @@ public Pig read(JsonReader in) throws IOException { return ret; } - throw new IOException(String.format("Failed deserialization for Pig: %d classes match result, expected 1. JSON: %s", match, jsonObject.toString())); + throw new IOException(String.format("Failed deserialization for Pig: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonObject.toString())); } }.nullSafe(); } @@ -258,11 +261,13 @@ public DanishPig getDanishPig() throws ClassCastException { public static void validateJsonObject(JsonObject jsonObj) throws IOException { // validate oneOf schemas one by one int validCount = 0; + ArrayList errorMessages = new ArrayList<>(); // validate the json string with BasquePig try { BasquePig.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for BasquePig failed with `%s`.", e.getMessage())); // continue to the next one } // validate the json string with DanishPig @@ -270,10 +275,11 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { DanishPig.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for DanishPig failed with `%s`.", e.getMessage())); // continue to the next one } if (validCount != 1) { - throw new IOException(String.format("The JSON string is invalid for Pig with oneOf schemas: BasquePig, DanishPig. %d class(es) match the result, expected 1. JSON: %s", validCount, jsonObj.toString())); + throw new IOException(String.format("The JSON string is invalid for Pig with oneOf schemas: BasquePig, DanishPig. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonObj.toString())); } } diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Quadrilateral.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Quadrilateral.java index 61b9d62aa028..14699135de60 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Quadrilateral.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Quadrilateral.java @@ -125,6 +125,7 @@ public Quadrilateral read(JsonReader in) throws IOException { } int match = 0; + ArrayList errorMessages = new ArrayList<>(); TypeAdapter actualAdapter = elementAdapter; // deserialize ComplexQuadrilateral @@ -136,6 +137,7 @@ public Quadrilateral read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'ComplexQuadrilateral'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for ComplexQuadrilateral failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'ComplexQuadrilateral'", e); } @@ -148,6 +150,7 @@ public Quadrilateral read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'SimpleQuadrilateral'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for SimpleQuadrilateral failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'SimpleQuadrilateral'", e); } @@ -157,7 +160,7 @@ public Quadrilateral read(JsonReader in) throws IOException { return ret; } - throw new IOException(String.format("Failed deserialization for Quadrilateral: %d classes match result, expected 1. JSON: %s", match, jsonObject.toString())); + throw new IOException(String.format("Failed deserialization for Quadrilateral: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonObject.toString())); } }.nullSafe(); } @@ -258,11 +261,13 @@ public SimpleQuadrilateral getSimpleQuadrilateral() throws ClassCastException { public static void validateJsonObject(JsonObject jsonObj) throws IOException { // validate oneOf schemas one by one int validCount = 0; + ArrayList errorMessages = new ArrayList<>(); // validate the json string with ComplexQuadrilateral try { ComplexQuadrilateral.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for ComplexQuadrilateral failed with `%s`.", e.getMessage())); // continue to the next one } // validate the json string with SimpleQuadrilateral @@ -270,10 +275,11 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { SimpleQuadrilateral.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for SimpleQuadrilateral failed with `%s`.", e.getMessage())); // continue to the next one } if (validCount != 1) { - throw new IOException(String.format("The JSON string is invalid for Quadrilateral with oneOf schemas: ComplexQuadrilateral, SimpleQuadrilateral. %d class(es) match the result, expected 1. JSON: %s", validCount, jsonObj.toString())); + throw new IOException(String.format("The JSON string is invalid for Quadrilateral with oneOf schemas: ComplexQuadrilateral, SimpleQuadrilateral. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonObj.toString())); } } diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Shape.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Shape.java index 8c0c9b2fc8b8..a2a9054865a7 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Shape.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Shape.java @@ -125,6 +125,7 @@ public Shape read(JsonReader in) throws IOException { } int match = 0; + ArrayList errorMessages = new ArrayList<>(); TypeAdapter actualAdapter = elementAdapter; // deserialize Quadrilateral @@ -136,6 +137,7 @@ public Shape read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'Quadrilateral'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for Quadrilateral failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'Quadrilateral'", e); } @@ -148,6 +150,7 @@ public Shape read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'Triangle'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for Triangle failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'Triangle'", e); } @@ -157,7 +160,7 @@ public Shape read(JsonReader in) throws IOException { return ret; } - throw new IOException(String.format("Failed deserialization for Shape: %d classes match result, expected 1. JSON: %s", match, jsonObject.toString())); + throw new IOException(String.format("Failed deserialization for Shape: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonObject.toString())); } }.nullSafe(); } @@ -258,11 +261,13 @@ public Triangle getTriangle() throws ClassCastException { public static void validateJsonObject(JsonObject jsonObj) throws IOException { // validate oneOf schemas one by one int validCount = 0; + ArrayList errorMessages = new ArrayList<>(); // validate the json string with Quadrilateral try { Quadrilateral.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for Quadrilateral failed with `%s`.", e.getMessage())); // continue to the next one } // validate the json string with Triangle @@ -270,10 +275,11 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { Triangle.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for Triangle failed with `%s`.", e.getMessage())); // continue to the next one } if (validCount != 1) { - throw new IOException(String.format("The JSON string is invalid for Shape with oneOf schemas: Quadrilateral, Triangle. %d class(es) match the result, expected 1. JSON: %s", validCount, jsonObj.toString())); + throw new IOException(String.format("The JSON string is invalid for Shape with oneOf schemas: Quadrilateral, Triangle. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonObj.toString())); } } diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/ShapeOrNull.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/ShapeOrNull.java index 28badafc0399..72367d230603 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/ShapeOrNull.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/ShapeOrNull.java @@ -125,6 +125,7 @@ public ShapeOrNull read(JsonReader in) throws IOException { } int match = 0; + ArrayList errorMessages = new ArrayList<>(); TypeAdapter actualAdapter = elementAdapter; // deserialize Quadrilateral @@ -136,6 +137,7 @@ public ShapeOrNull read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'Quadrilateral'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for Quadrilateral failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'Quadrilateral'", e); } @@ -148,6 +150,7 @@ public ShapeOrNull read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'Triangle'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for Triangle failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'Triangle'", e); } @@ -157,7 +160,7 @@ public ShapeOrNull read(JsonReader in) throws IOException { return ret; } - throw new IOException(String.format("Failed deserialization for ShapeOrNull: %d classes match result, expected 1. JSON: %s", match, jsonObject.toString())); + throw new IOException(String.format("Failed deserialization for ShapeOrNull: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonObject.toString())); } }.nullSafe(); } @@ -263,11 +266,13 @@ public Triangle getTriangle() throws ClassCastException { public static void validateJsonObject(JsonObject jsonObj) throws IOException { // validate oneOf schemas one by one int validCount = 0; + ArrayList errorMessages = new ArrayList<>(); // validate the json string with Quadrilateral try { Quadrilateral.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for Quadrilateral failed with `%s`.", e.getMessage())); // continue to the next one } // validate the json string with Triangle @@ -275,10 +280,11 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { Triangle.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for Triangle failed with `%s`.", e.getMessage())); // continue to the next one } if (validCount != 1) { - throw new IOException(String.format("The JSON string is invalid for ShapeOrNull with oneOf schemas: Quadrilateral, Triangle. %d class(es) match the result, expected 1. JSON: %s", validCount, jsonObj.toString())); + throw new IOException(String.format("The JSON string is invalid for ShapeOrNull with oneOf schemas: Quadrilateral, Triangle. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonObj.toString())); } } diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Triangle.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Triangle.java index 3dea796aea18..512cd7fbf1a9 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Triangle.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/Triangle.java @@ -138,6 +138,7 @@ public Triangle read(JsonReader in) throws IOException { } int match = 0; + ArrayList errorMessages = new ArrayList<>(); TypeAdapter actualAdapter = elementAdapter; // deserialize EquilateralTriangle @@ -149,6 +150,7 @@ public Triangle read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'EquilateralTriangle'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for EquilateralTriangle failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'EquilateralTriangle'", e); } @@ -161,6 +163,7 @@ public Triangle read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'IsoscelesTriangle'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for IsoscelesTriangle failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'IsoscelesTriangle'", e); } @@ -173,6 +176,7 @@ public Triangle read(JsonReader in) throws IOException { log.log(Level.FINER, "Input data matches schema 'ScaleneTriangle'"); } catch (Exception e) { // deserialization failed, continue + errorMessages.add(String.format("Deserialization for ScaleneTriangle failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'ScaleneTriangle'", e); } @@ -182,7 +186,7 @@ public Triangle read(JsonReader in) throws IOException { return ret; } - throw new IOException(String.format("Failed deserialization for Triangle: %d classes match result, expected 1. JSON: %s", match, jsonObject.toString())); + throw new IOException(String.format("Failed deserialization for Triangle: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonObject.toString())); } }.nullSafe(); } @@ -306,11 +310,13 @@ public ScaleneTriangle getScaleneTriangle() throws ClassCastException { public static void validateJsonObject(JsonObject jsonObj) throws IOException { // validate oneOf schemas one by one int validCount = 0; + ArrayList errorMessages = new ArrayList<>(); // validate the json string with EquilateralTriangle try { EquilateralTriangle.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for EquilateralTriangle failed with `%s`.", e.getMessage())); // continue to the next one } // validate the json string with IsoscelesTriangle @@ -318,6 +324,7 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { IsoscelesTriangle.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for IsoscelesTriangle failed with `%s`.", e.getMessage())); // continue to the next one } // validate the json string with ScaleneTriangle @@ -325,10 +332,11 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { ScaleneTriangle.validateJsonObject(jsonObj); validCount++; } catch (Exception e) { + errorMessages.add(String.format("Deserialization for ScaleneTriangle failed with `%s`.", e.getMessage())); // continue to the next one } if (validCount != 1) { - throw new IOException(String.format("The JSON string is invalid for Triangle with oneOf schemas: EquilateralTriangle, IsoscelesTriangle, ScaleneTriangle. %d class(es) match the result, expected 1. JSON: %s", validCount, jsonObj.toString())); + throw new IOException(String.format("The JSON string is invalid for Triangle with oneOf schemas: EquilateralTriangle, IsoscelesTriangle, ScaleneTriangle. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonObj.toString())); } } diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/JSONTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/JSONTest.java index b24033df2e98..889ac0719087 100644 --- a/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/JSONTest.java +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/JSONTest.java @@ -429,7 +429,7 @@ public void testOneOfSchemaWithDiscriminator() throws Exception { Exception exception = assertThrows(com.google.gson.JsonSyntaxException.class, () -> { Mammal o = json.getGson().fromJson(str, Mammal.class); }); - assertTrue(exception.getMessage().contains("Failed deserialization for Mammal: 0 classes match result, expected 1. JSON: {\"cultivar\":\"golden delicious\",\"mealy\":false,\"garbage_prop\":\"abc\"}")); + assertEquals("java.io.IOException: Failed deserialization for Mammal: 0 classes match result, expected 1. Detailed failure message for oneOf schemas: [Deserialization for Pig failed with `The JSON string is invalid for Pig with oneOf schemas: BasquePig, DanishPig. 0 class(es) match the result, expected 1. Detailed failure message for oneOf schemas: [Deserialization for BasquePig failed with `The required field `className` is not found in the JSON string: {\"cultivar\":\"golden delicious\",\"mealy\":false,\"garbage_prop\":\"abc\"}`., Deserialization for DanishPig failed with `The required field `className` is not found in the JSON string: {\"cultivar\":\"golden delicious\",\"mealy\":false,\"garbage_prop\":\"abc\"}`.]. JSON: {\"cultivar\":\"golden delicious\",\"mealy\":false,\"garbage_prop\":\"abc\"}`., Deserialization for Whale failed with `The required field `className` is not found in the JSON string: {\"cultivar\":\"golden delicious\",\"mealy\":false,\"garbage_prop\":\"abc\"}`., Deserialization for Zebra failed with `The required field `className` is not found in the JSON string: {\"cultivar\":\"golden delicious\",\"mealy\":false,\"garbage_prop\":\"abc\"}`.]. JSON: {\"cultivar\":\"golden delicious\",\"mealy\":false,\"garbage_prop\":\"abc\"}", exception.getMessage()); } { // Try to deserialize empty object. This should fail 'oneOf' because none will match @@ -438,7 +438,7 @@ public void testOneOfSchemaWithDiscriminator() throws Exception { Exception exception = assertThrows(com.google.gson.JsonSyntaxException.class, () -> { json.getGson().fromJson(str, Mammal.class); }); - assertTrue(exception.getMessage().contains("Failed deserialization for Mammal: 0 classes match result, expected 1")); + assertEquals("java.io.IOException: Failed deserialization for Mammal: 0 classes match result, expected 1. Detailed failure message for oneOf schemas: [Deserialization for Pig failed with `The JSON string is invalid for Pig with oneOf schemas: BasquePig, DanishPig. 0 class(es) match the result, expected 1. Detailed failure message for oneOf schemas: [Deserialization for BasquePig failed with `The required field `className` is not found in the JSON string: {}`., Deserialization for DanishPig failed with `The required field `className` is not found in the JSON string: {}`.]. JSON: {}`., Deserialization for Whale failed with `The required field `className` is not found in the JSON string: {}`., Deserialization for Zebra failed with `The required field `className` is not found in the JSON string: {}`.]. JSON: {}", exception.getMessage()); } } @@ -517,7 +517,7 @@ public void testOneOfSchemaWithoutDiscriminator() throws Exception { Exception exception = assertThrows(com.google.gson.JsonSyntaxException.class, () -> { FruitReq o = json.getGson().fromJson(str, FruitReq.class); }); - assertTrue(exception.getMessage().contains("Failed deserialization for FruitReq: 0 classes match result, expected 1. JSON: {\"cultivar\":\"golden delicious\",\"mealy\":false,\"garbage_prop\":\"abc\"}")); + assertEquals("java.io.IOException: Failed deserialization for FruitReq: 0 classes match result, expected 1. Detailed failure message for oneOf schemas: [Deserialization for AppleReq failed with `The field `garbage_prop` in the JSON string is not defined in the `AppleReq` properties. JSON: {\"cultivar\":\"golden delicious\",\"mealy\":false,\"garbage_prop\":\"abc\"}`., Deserialization for BananaReq failed with `The field `cultivar` in the JSON string is not defined in the `BananaReq` properties. JSON: {\"cultivar\":\"golden delicious\",\"mealy\":false,\"garbage_prop\":\"abc\"}`.]. JSON: {\"cultivar\":\"golden delicious\",\"mealy\":false,\"garbage_prop\":\"abc\"}", exception.getMessage()); } { String str = "{ \"lengthCm\": 17 }";