forked from loafle/openapi-generator-original
fix oneOf discriminator lookup in java okhttp-gson client (#11735)
This commit is contained in:
parent
33b89148e5
commit
b0877a112d
@ -6,3 +6,4 @@ templateDir: modules/openapi-generator/src/main/resources/Java
|
|||||||
additionalProperties:
|
additionalProperties:
|
||||||
artifactId: petstore-okhttp-gson
|
artifactId: petstore-okhttp-gson
|
||||||
hideGenerationTimestamp: "true"
|
hideGenerationTimestamp: "true"
|
||||||
|
useOneOfDiscriminatorLookup: "true"
|
||||||
|
@ -76,8 +76,11 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im
|
|||||||
{{#discriminator}}
|
{{#discriminator}}
|
||||||
// use discriminator value for faster oneOf lookup
|
// use discriminator value for faster oneOf lookup
|
||||||
{{classname}} new{{classname}} = new {{classname}}();
|
{{classname}} new{{classname}} = new {{classname}}();
|
||||||
String discriminatorValue = elementAdapter.read(in).getAsJsonObject().get("{{{propertyBaseName}}}").getAsString();
|
if (jsonObject.get("{{{propertyBaseName}}}") == null) {
|
||||||
switch (discriminatorValue) {
|
log.log(Level.WARNING, "Failed to lookup discriminator value for {{classname}} as `{{{propertyBaseName}}}` was not found in the payload or the payload is empty.");
|
||||||
|
} else {
|
||||||
|
// look up the discriminator value in the field `{{{propertyBaseName}}}`
|
||||||
|
switch (jsonObject.get("{{{propertyBaseName}}}").getAsString()) {
|
||||||
{{#mappedModels}}
|
{{#mappedModels}}
|
||||||
case "{{{mappingName}}}":
|
case "{{{mappingName}}}":
|
||||||
deserialized = adapter{{modelName}}.fromJsonTree(jsonObject);
|
deserialized = adapter{{modelName}}.fromJsonTree(jsonObject);
|
||||||
@ -85,7 +88,8 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im
|
|||||||
return new{{classname}};
|
return new{{classname}};
|
||||||
{{/mappedModels}}
|
{{/mappedModels}}
|
||||||
default:
|
default:
|
||||||
log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", discriminatorValue));
|
log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", jsonObject.get("{{{propertyBaseName}}}").getAsString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{{/discriminator}}
|
{{/discriminator}}
|
||||||
|
@ -113,6 +113,30 @@ public class Mammal extends AbstractOpenApiSchema {
|
|||||||
Object deserialized = null;
|
Object deserialized = null;
|
||||||
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
||||||
|
|
||||||
|
// use discriminator value for faster oneOf lookup
|
||||||
|
Mammal newMammal = new Mammal();
|
||||||
|
if (jsonObject.get("className") == null) {
|
||||||
|
log.log(Level.WARNING, "Failed to lookup discriminator value for Mammal as `className` was not found in the payload or the payload is empty.");
|
||||||
|
} else {
|
||||||
|
// look up the discriminator value in the field `className`
|
||||||
|
switch (jsonObject.get("className").getAsString()) {
|
||||||
|
case "Pig":
|
||||||
|
deserialized = adapterPig.fromJsonTree(jsonObject);
|
||||||
|
newMammal.setActualInstance(deserialized);
|
||||||
|
return newMammal;
|
||||||
|
case "whale":
|
||||||
|
deserialized = adapterWhale.fromJsonTree(jsonObject);
|
||||||
|
newMammal.setActualInstance(deserialized);
|
||||||
|
return newMammal;
|
||||||
|
case "zebra":
|
||||||
|
deserialized = adapterZebra.fromJsonTree(jsonObject);
|
||||||
|
newMammal.setActualInstance(deserialized);
|
||||||
|
return newMammal;
|
||||||
|
default:
|
||||||
|
log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for Mammal. Possible values: Pig whale zebra", jsonObject.get("className").getAsString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int match = 0;
|
int match = 0;
|
||||||
TypeAdapter actualAdapter = elementAdapter;
|
TypeAdapter actualAdapter = elementAdapter;
|
||||||
|
|
||||||
|
@ -104,6 +104,26 @@ public class NullableShape extends AbstractOpenApiSchema {
|
|||||||
Object deserialized = null;
|
Object deserialized = null;
|
||||||
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
||||||
|
|
||||||
|
// use discriminator value for faster oneOf lookup
|
||||||
|
NullableShape newNullableShape = new NullableShape();
|
||||||
|
if (jsonObject.get("shapeType") == null) {
|
||||||
|
log.log(Level.WARNING, "Failed to lookup discriminator value for NullableShape as `shapeType` was not found in the payload or the payload is empty.");
|
||||||
|
} else {
|
||||||
|
// look up the discriminator value in the field `shapeType`
|
||||||
|
switch (jsonObject.get("shapeType").getAsString()) {
|
||||||
|
case "Quadrilateral":
|
||||||
|
deserialized = adapterQuadrilateral.fromJsonTree(jsonObject);
|
||||||
|
newNullableShape.setActualInstance(deserialized);
|
||||||
|
return newNullableShape;
|
||||||
|
case "Triangle":
|
||||||
|
deserialized = adapterTriangle.fromJsonTree(jsonObject);
|
||||||
|
newNullableShape.setActualInstance(deserialized);
|
||||||
|
return newNullableShape;
|
||||||
|
default:
|
||||||
|
log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for NullableShape. Possible values: Quadrilateral Triangle", jsonObject.get("shapeType").getAsString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int match = 0;
|
int match = 0;
|
||||||
TypeAdapter actualAdapter = elementAdapter;
|
TypeAdapter actualAdapter = elementAdapter;
|
||||||
|
|
||||||
|
@ -104,6 +104,26 @@ public class Pig extends AbstractOpenApiSchema {
|
|||||||
Object deserialized = null;
|
Object deserialized = null;
|
||||||
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
||||||
|
|
||||||
|
// use discriminator value for faster oneOf lookup
|
||||||
|
Pig newPig = new Pig();
|
||||||
|
if (jsonObject.get("className") == null) {
|
||||||
|
log.log(Level.WARNING, "Failed to lookup discriminator value for Pig as `className` was not found in the payload or the payload is empty.");
|
||||||
|
} else {
|
||||||
|
// look up the discriminator value in the field `className`
|
||||||
|
switch (jsonObject.get("className").getAsString()) {
|
||||||
|
case "BasquePig":
|
||||||
|
deserialized = adapterBasquePig.fromJsonTree(jsonObject);
|
||||||
|
newPig.setActualInstance(deserialized);
|
||||||
|
return newPig;
|
||||||
|
case "DanishPig":
|
||||||
|
deserialized = adapterDanishPig.fromJsonTree(jsonObject);
|
||||||
|
newPig.setActualInstance(deserialized);
|
||||||
|
return newPig;
|
||||||
|
default:
|
||||||
|
log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for Pig. Possible values: BasquePig DanishPig", jsonObject.get("className").getAsString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int match = 0;
|
int match = 0;
|
||||||
TypeAdapter actualAdapter = elementAdapter;
|
TypeAdapter actualAdapter = elementAdapter;
|
||||||
|
|
||||||
|
@ -104,6 +104,26 @@ public class Quadrilateral extends AbstractOpenApiSchema {
|
|||||||
Object deserialized = null;
|
Object deserialized = null;
|
||||||
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
||||||
|
|
||||||
|
// use discriminator value for faster oneOf lookup
|
||||||
|
Quadrilateral newQuadrilateral = new Quadrilateral();
|
||||||
|
if (jsonObject.get("quadrilateralType") == null) {
|
||||||
|
log.log(Level.WARNING, "Failed to lookup discriminator value for Quadrilateral as `quadrilateralType` was not found in the payload or the payload is empty.");
|
||||||
|
} else {
|
||||||
|
// look up the discriminator value in the field `quadrilateralType`
|
||||||
|
switch (jsonObject.get("quadrilateralType").getAsString()) {
|
||||||
|
case "ComplexQuadrilateral":
|
||||||
|
deserialized = adapterComplexQuadrilateral.fromJsonTree(jsonObject);
|
||||||
|
newQuadrilateral.setActualInstance(deserialized);
|
||||||
|
return newQuadrilateral;
|
||||||
|
case "SimpleQuadrilateral":
|
||||||
|
deserialized = adapterSimpleQuadrilateral.fromJsonTree(jsonObject);
|
||||||
|
newQuadrilateral.setActualInstance(deserialized);
|
||||||
|
return newQuadrilateral;
|
||||||
|
default:
|
||||||
|
log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for Quadrilateral. Possible values: ComplexQuadrilateral SimpleQuadrilateral", jsonObject.get("quadrilateralType").getAsString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int match = 0;
|
int match = 0;
|
||||||
TypeAdapter actualAdapter = elementAdapter;
|
TypeAdapter actualAdapter = elementAdapter;
|
||||||
|
|
||||||
|
@ -104,6 +104,26 @@ public class Shape extends AbstractOpenApiSchema {
|
|||||||
Object deserialized = null;
|
Object deserialized = null;
|
||||||
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
||||||
|
|
||||||
|
// use discriminator value for faster oneOf lookup
|
||||||
|
Shape newShape = new Shape();
|
||||||
|
if (jsonObject.get("shapeType") == null) {
|
||||||
|
log.log(Level.WARNING, "Failed to lookup discriminator value for Shape as `shapeType` was not found in the payload or the payload is empty.");
|
||||||
|
} else {
|
||||||
|
// look up the discriminator value in the field `shapeType`
|
||||||
|
switch (jsonObject.get("shapeType").getAsString()) {
|
||||||
|
case "Quadrilateral":
|
||||||
|
deserialized = adapterQuadrilateral.fromJsonTree(jsonObject);
|
||||||
|
newShape.setActualInstance(deserialized);
|
||||||
|
return newShape;
|
||||||
|
case "Triangle":
|
||||||
|
deserialized = adapterTriangle.fromJsonTree(jsonObject);
|
||||||
|
newShape.setActualInstance(deserialized);
|
||||||
|
return newShape;
|
||||||
|
default:
|
||||||
|
log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for Shape. Possible values: Quadrilateral Triangle", jsonObject.get("shapeType").getAsString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int match = 0;
|
int match = 0;
|
||||||
TypeAdapter actualAdapter = elementAdapter;
|
TypeAdapter actualAdapter = elementAdapter;
|
||||||
|
|
||||||
|
@ -104,6 +104,26 @@ public class ShapeOrNull extends AbstractOpenApiSchema {
|
|||||||
Object deserialized = null;
|
Object deserialized = null;
|
||||||
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
||||||
|
|
||||||
|
// use discriminator value for faster oneOf lookup
|
||||||
|
ShapeOrNull newShapeOrNull = new ShapeOrNull();
|
||||||
|
if (jsonObject.get("shapeType") == null) {
|
||||||
|
log.log(Level.WARNING, "Failed to lookup discriminator value for ShapeOrNull as `shapeType` was not found in the payload or the payload is empty.");
|
||||||
|
} else {
|
||||||
|
// look up the discriminator value in the field `shapeType`
|
||||||
|
switch (jsonObject.get("shapeType").getAsString()) {
|
||||||
|
case "Quadrilateral":
|
||||||
|
deserialized = adapterQuadrilateral.fromJsonTree(jsonObject);
|
||||||
|
newShapeOrNull.setActualInstance(deserialized);
|
||||||
|
return newShapeOrNull;
|
||||||
|
case "Triangle":
|
||||||
|
deserialized = adapterTriangle.fromJsonTree(jsonObject);
|
||||||
|
newShapeOrNull.setActualInstance(deserialized);
|
||||||
|
return newShapeOrNull;
|
||||||
|
default:
|
||||||
|
log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for ShapeOrNull. Possible values: Quadrilateral Triangle", jsonObject.get("shapeType").getAsString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int match = 0;
|
int match = 0;
|
||||||
TypeAdapter actualAdapter = elementAdapter;
|
TypeAdapter actualAdapter = elementAdapter;
|
||||||
|
|
||||||
|
@ -113,6 +113,30 @@ public class Triangle extends AbstractOpenApiSchema {
|
|||||||
Object deserialized = null;
|
Object deserialized = null;
|
||||||
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();
|
||||||
|
|
||||||
|
// use discriminator value for faster oneOf lookup
|
||||||
|
Triangle newTriangle = new Triangle();
|
||||||
|
if (jsonObject.get("triangleType") == null) {
|
||||||
|
log.log(Level.WARNING, "Failed to lookup discriminator value for Triangle as `triangleType` was not found in the payload or the payload is empty.");
|
||||||
|
} else {
|
||||||
|
// look up the discriminator value in the field `triangleType`
|
||||||
|
switch (jsonObject.get("triangleType").getAsString()) {
|
||||||
|
case "EquilateralTriangle":
|
||||||
|
deserialized = adapterEquilateralTriangle.fromJsonTree(jsonObject);
|
||||||
|
newTriangle.setActualInstance(deserialized);
|
||||||
|
return newTriangle;
|
||||||
|
case "IsoscelesTriangle":
|
||||||
|
deserialized = adapterIsoscelesTriangle.fromJsonTree(jsonObject);
|
||||||
|
newTriangle.setActualInstance(deserialized);
|
||||||
|
return newTriangle;
|
||||||
|
case "ScaleneTriangle":
|
||||||
|
deserialized = adapterScaleneTriangle.fromJsonTree(jsonObject);
|
||||||
|
newTriangle.setActualInstance(deserialized);
|
||||||
|
return newTriangle;
|
||||||
|
default:
|
||||||
|
log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for Triangle. Possible values: EquilateralTriangle IsoscelesTriangle ScaleneTriangle", jsonObject.get("triangleType").getAsString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int match = 0;
|
int match = 0;
|
||||||
TypeAdapter actualAdapter = elementAdapter;
|
TypeAdapter actualAdapter = elementAdapter;
|
||||||
|
|
||||||
|
@ -364,6 +364,65 @@ public class JSONTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate a oneOf schema can be deserialized into the expected class.
|
||||||
|
* The oneOf schema has a discriminator.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testOneOfSchemaWithDiscriminator() throws Exception {
|
||||||
|
{
|
||||||
|
String str = "{ \"className\": \"whale\", \"hasBaleen\": false, \"hasTeeth\": false }";
|
||||||
|
|
||||||
|
// make sure deserialization works for pojo object
|
||||||
|
Whale w = json.getGson().fromJson(str, Whale.class);
|
||||||
|
assertEquals(w.getClassName(), "whale");
|
||||||
|
assertEquals(w.getHasBaleen(), false);
|
||||||
|
assertEquals(w.getHasTeeth(), false);
|
||||||
|
|
||||||
|
Mammal o = json.getGson().fromJson(str, Mammal.class);
|
||||||
|
assertTrue(o.getActualInstance() instanceof Whale);
|
||||||
|
Whale inst = (Whale) o.getActualInstance();
|
||||||
|
assertEquals(inst.getClassName(), "whale");
|
||||||
|
assertEquals(inst.getHasBaleen(), false);
|
||||||
|
assertEquals(inst.getHasTeeth(), false);
|
||||||
|
assertEquals(json.getGson().toJson(inst), "{\"hasBaleen\":false,\"hasTeeth\":false,\"className\":\"whale\"}");
|
||||||
|
assertEquals(inst.toJson(), "{\"hasBaleen\":false,\"hasTeeth\":false,\"className\":\"whale\"}");
|
||||||
|
assertEquals(json.getGson().toJson(o), "{\"hasBaleen\":false,\"hasTeeth\":false,\"className\":\"whale\"}");
|
||||||
|
assertEquals(o.toJson(), "{\"hasBaleen\":false,\"hasTeeth\":false,\"className\":\"whale\"}");
|
||||||
|
|
||||||
|
String str2 = "{ \"className\": \"zebra\", \"type\": \"plains\" }";
|
||||||
|
|
||||||
|
// make sure deserialization works for pojo object
|
||||||
|
Zebra z = Zebra.fromJson(str2);
|
||||||
|
assertEquals(z.toJson(), "{\"className\":\"zebra\",\"type\":\"plains\"}");
|
||||||
|
|
||||||
|
Mammal o2 = json.getGson().fromJson(str2, Mammal.class);
|
||||||
|
assertTrue(o2.getActualInstance() instanceof Zebra);
|
||||||
|
Zebra inst2 = (Zebra) o2.getActualInstance();
|
||||||
|
assertEquals(json.getGson().toJson(inst2), "{\"className\":\"zebra\",\"type\":\"plains\"}");
|
||||||
|
assertEquals(inst2.toJson(), "{\"className\":\"zebra\",\"type\":\"plains\"}");
|
||||||
|
assertEquals(json.getGson().toJson(o2), "{\"className\":\"zebra\",\"type\":\"plains\"}");
|
||||||
|
assertEquals(o2.toJson(), "{\"className\":\"zebra\",\"type\":\"plains\"}");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// incorrect payload results in exception
|
||||||
|
String str = "{ \"cultivar\": \"golden delicious\", \"mealy\": false, \"garbage_prop\": \"abc\" }";
|
||||||
|
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\"}"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Try to deserialize empty object. This should fail 'oneOf' because none will match
|
||||||
|
// whale or zebra.
|
||||||
|
String str = "{ }";
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate a oneOf schema can be deserialized into the expected class.
|
* Validate a oneOf schema can be deserialized into the expected class.
|
||||||
* The oneOf schema does not have a discriminator.
|
* The oneOf schema does not have a discriminator.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user