better error messages for oneOf in java okhttp-gson (#12311)

This commit is contained in:
William Cheng 2022-05-10 17:16:02 +08:00 committed by GitHub
parent ad3b5f7045
commit 68360cab92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 85 additions and 23 deletions

View File

@ -95,6 +95,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im
{{/discriminator}}
{{/useOneOfDiscriminatorLookup}}
int match = 0;
ArrayList<String> 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<String> 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()));
}
}

View File

@ -106,6 +106,7 @@ public class Fruit extends AbstractOpenApiSchema {
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
int match = 0;
ArrayList<String> errorMessages = new ArrayList<>();
TypeAdapter actualAdapter = elementAdapter;
// deserialize Apple
@ -117,6 +118,7 @@ public class Fruit extends AbstractOpenApiSchema {
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 class Fruit extends AbstractOpenApiSchema {
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 class Fruit extends AbstractOpenApiSchema {
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 class Fruit extends AbstractOpenApiSchema {
public static void validateJsonObject(JsonObject jsonObj) throws IOException {
// validate oneOf schemas one by one
int validCount = 0;
ArrayList<String> 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 class Fruit extends AbstractOpenApiSchema {
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()));
}
}

View File

@ -106,6 +106,7 @@ public class FruitReq extends AbstractOpenApiSchema {
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
int match = 0;
ArrayList<String> errorMessages = new ArrayList<>();
TypeAdapter actualAdapter = elementAdapter;
// deserialize AppleReq
@ -117,6 +118,7 @@ public class FruitReq extends AbstractOpenApiSchema {
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 class FruitReq extends AbstractOpenApiSchema {
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 class FruitReq extends AbstractOpenApiSchema {
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 class FruitReq extends AbstractOpenApiSchema {
public static void validateJsonObject(JsonObject jsonObj) throws IOException {
// validate oneOf schemas one by one
int validCount = 0;
ArrayList<String> 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 class FruitReq extends AbstractOpenApiSchema {
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()));
}
}

View File

@ -138,6 +138,7 @@ public class Mammal extends AbstractOpenApiSchema {
}
int match = 0;
ArrayList<String> errorMessages = new ArrayList<>();
TypeAdapter actualAdapter = elementAdapter;
// deserialize Pig
@ -149,6 +150,7 @@ public class Mammal extends AbstractOpenApiSchema {
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 class Mammal extends AbstractOpenApiSchema {
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 class Mammal extends AbstractOpenApiSchema {
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 class Mammal extends AbstractOpenApiSchema {
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 class Mammal extends AbstractOpenApiSchema {
public static void validateJsonObject(JsonObject jsonObj) throws IOException {
// validate oneOf schemas one by one
int validCount = 0;
ArrayList<String> 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 class Mammal extends AbstractOpenApiSchema {
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 class Mammal extends AbstractOpenApiSchema {
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()));
}
}

View File

@ -125,6 +125,7 @@ public class NullableShape extends AbstractOpenApiSchema {
}
int match = 0;
ArrayList<String> errorMessages = new ArrayList<>();
TypeAdapter actualAdapter = elementAdapter;
// deserialize Quadrilateral
@ -136,6 +137,7 @@ public class NullableShape extends AbstractOpenApiSchema {
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 class NullableShape extends AbstractOpenApiSchema {
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 class NullableShape extends AbstractOpenApiSchema {
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 class NullableShape extends AbstractOpenApiSchema {
public static void validateJsonObject(JsonObject jsonObj) throws IOException {
// validate oneOf schemas one by one
int validCount = 0;
ArrayList<String> 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 class NullableShape extends AbstractOpenApiSchema {
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()));
}
}

View File

@ -125,6 +125,7 @@ public class Pig extends AbstractOpenApiSchema {
}
int match = 0;
ArrayList<String> errorMessages = new ArrayList<>();
TypeAdapter actualAdapter = elementAdapter;
// deserialize BasquePig
@ -136,6 +137,7 @@ public class Pig extends AbstractOpenApiSchema {
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 class Pig extends AbstractOpenApiSchema {
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 class Pig extends AbstractOpenApiSchema {
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 class Pig extends AbstractOpenApiSchema {
public static void validateJsonObject(JsonObject jsonObj) throws IOException {
// validate oneOf schemas one by one
int validCount = 0;
ArrayList<String> 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 class Pig extends AbstractOpenApiSchema {
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()));
}
}

View File

@ -125,6 +125,7 @@ public class Quadrilateral extends AbstractOpenApiSchema {
}
int match = 0;
ArrayList<String> errorMessages = new ArrayList<>();
TypeAdapter actualAdapter = elementAdapter;
// deserialize ComplexQuadrilateral
@ -136,6 +137,7 @@ public class Quadrilateral extends AbstractOpenApiSchema {
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 class Quadrilateral extends AbstractOpenApiSchema {
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 class Quadrilateral extends AbstractOpenApiSchema {
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 class Quadrilateral extends AbstractOpenApiSchema {
public static void validateJsonObject(JsonObject jsonObj) throws IOException {
// validate oneOf schemas one by one
int validCount = 0;
ArrayList<String> 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 class Quadrilateral extends AbstractOpenApiSchema {
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()));
}
}

View File

@ -125,6 +125,7 @@ public class Shape extends AbstractOpenApiSchema {
}
int match = 0;
ArrayList<String> errorMessages = new ArrayList<>();
TypeAdapter actualAdapter = elementAdapter;
// deserialize Quadrilateral
@ -136,6 +137,7 @@ public class Shape extends AbstractOpenApiSchema {
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 class Shape extends AbstractOpenApiSchema {
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 class Shape extends AbstractOpenApiSchema {
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 class Shape extends AbstractOpenApiSchema {
public static void validateJsonObject(JsonObject jsonObj) throws IOException {
// validate oneOf schemas one by one
int validCount = 0;
ArrayList<String> 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 class Shape extends AbstractOpenApiSchema {
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()));
}
}

View File

@ -125,6 +125,7 @@ public class ShapeOrNull extends AbstractOpenApiSchema {
}
int match = 0;
ArrayList<String> errorMessages = new ArrayList<>();
TypeAdapter actualAdapter = elementAdapter;
// deserialize Quadrilateral
@ -136,6 +137,7 @@ public class ShapeOrNull extends AbstractOpenApiSchema {
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 class ShapeOrNull extends AbstractOpenApiSchema {
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 class ShapeOrNull extends AbstractOpenApiSchema {
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 class ShapeOrNull extends AbstractOpenApiSchema {
public static void validateJsonObject(JsonObject jsonObj) throws IOException {
// validate oneOf schemas one by one
int validCount = 0;
ArrayList<String> 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 class ShapeOrNull extends AbstractOpenApiSchema {
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()));
}
}

View File

@ -138,6 +138,7 @@ public class Triangle extends AbstractOpenApiSchema {
}
int match = 0;
ArrayList<String> errorMessages = new ArrayList<>();
TypeAdapter actualAdapter = elementAdapter;
// deserialize EquilateralTriangle
@ -149,6 +150,7 @@ public class Triangle extends AbstractOpenApiSchema {
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 class Triangle extends AbstractOpenApiSchema {
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 class Triangle extends AbstractOpenApiSchema {
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 class Triangle extends AbstractOpenApiSchema {
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 class Triangle extends AbstractOpenApiSchema {
public static void validateJsonObject(JsonObject jsonObj) throws IOException {
// validate oneOf schemas one by one
int validCount = 0;
ArrayList<String> 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 class Triangle extends AbstractOpenApiSchema {
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 class Triangle extends AbstractOpenApiSchema {
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()));
}
}

View File

@ -429,7 +429,7 @@ public class JSONTest {
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 class JSONTest {
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 class JSONTest {
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 }";