From dad10ce9605abcd0ac181999603393f3effbfa26 Mon Sep 17 00:00:00 2001 From: unkish <3533269+unkish@users.noreply.github.com> Date: Wed, 21 Dec 2022 11:27:19 +0200 Subject: [PATCH] Use Object as the type in case schema property contains mixed types Closes #1425 --- .../org/jsonschema2pojo/rules/TypeRule.java | 24 ++++++++++++------- .../jsonschema2pojo/integration/TypeIT.java | 20 +++++++++++++--- .../integration/yaml/YamlTypeIT.java | 20 +++++++++++++--- .../schema/type/mixedUnionTypes.json | 11 +++++++++ .../resources/schema/type/unionTypes.json | 7 ++++-- .../schema/yaml/type/mixedUnionTypes.yaml | 11 +++++++++ .../schema/yaml/type/unionTypes.yaml | 9 ++++--- 7 files changed, 82 insertions(+), 20 deletions(-) create mode 100644 jsonschema2pojo-integration-tests/src/test/resources/schema/type/mixedUnionTypes.json create mode 100644 jsonschema2pojo-integration-tests/src/test/resources/schema/yaml/type/mixedUnionTypes.yaml diff --git a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/TypeRule.java b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/TypeRule.java index b9284707f..36690f87f 100644 --- a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/TypeRule.java +++ b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/TypeRule.java @@ -21,6 +21,9 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import org.jsonschema2pojo.GenerationConfig; import org.jsonschema2pojo.Schema; @@ -119,19 +122,22 @@ public JType apply(String nodeName, JsonNode node, JsonNode parent, JClassContai } private String getTypeName(JsonNode node) { - if (node.has("type") && node.get("type").isArray() && node.get("type").size() > 0) { - for (JsonNode jsonNode : node.get("type")) { - String typeName = jsonNode.asText(); - if (!typeName.equals("null")) { - return typeName; + if (node.has("type")) { + final JsonNode typeNode = node.get("type"); + if (typeNode.isArray() && typeNode.size() > 0) { + final List typeValues = StreamSupport.stream(typeNode.spliterator(), false) + .map(JsonNode::asText) + .filter(n -> !"null".equals(n)) + .collect(Collectors.toList()); + + if (typeValues.size() == 1) { + return typeValues.get(0); } + } else if (typeNode.isTextual()) { + return typeNode.asText(); } } - if (node.has("type") && node.get("type").isTextual()) { - return node.get("type").asText(); - } - return DEFAULT_TYPE_NAME; } diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/TypeIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/TypeIT.java index 5bf7f3ff1..42dcf0b20 100644 --- a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/TypeIT.java +++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/TypeIT.java @@ -282,13 +282,13 @@ public void useDoubleNumbersFalseCausesPrimitiveNumbersToBecomeFloats() throws C } @Test - public void unionTypesChooseFirstTypePresent() throws ClassNotFoundException, SecurityException, NoSuchMethodException { + public void unionTypesChooseFirstTypePresent() throws ReflectiveOperationException { Class classWithUnionProperties = schemaRule.generateAndCompile("/schema/type/unionTypes.json", "com.example").loadClass("com.example.UnionTypes"); - Method booleanGetter = classWithUnionProperties.getMethod("getBooleanProperty"); + Method nullTypeGetter = classWithUnionProperties.getMethod("getNullProperty"); - assertThat(booleanGetter.getReturnType().getName(), is("java.lang.Boolean")); + assertThat(nullTypeGetter.getReturnType().getName(), is("java.lang.Object")); Method stringGetter = classWithUnionProperties.getMethod("getStringProperty"); @@ -297,6 +297,20 @@ public void unionTypesChooseFirstTypePresent() throws ClassNotFoundException, Se Method integerGetter = classWithUnionProperties.getMethod("getIntegerProperty"); assertThat(integerGetter.getReturnType().getName(), is("java.lang.Integer")); + + Method booleanGetter = classWithUnionProperties.getMethod("getBooleanProperty"); + assertThat(booleanGetter.getReturnType().getName(), is("java.lang.Boolean")); + } + + @Test + public void mixedUnionTypesReturnObject() throws ReflectiveOperationException { + Class classWithMixedUnionProperties = schemaRule.generateAndCompile("/schema/type/mixedUnionTypes.json", "com.example").loadClass("com.example.MixedUnionTypes"); + + Method mixedTypesGetter = classWithMixedUnionProperties.getMethod("getMixedTypesProperty"); + assertThat(mixedTypesGetter.getReturnType().getName(), is("java.lang.Object")); + + Method mixedTypesWithNullGetter = classWithMixedUnionProperties.getMethod("getMixedTypesWithNullProperty"); + assertThat(mixedTypesWithNullGetter.getReturnType().getName(), is("java.lang.Object")); } @SuppressWarnings("rawtypes") diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/yaml/YamlTypeIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/yaml/YamlTypeIT.java index 19109cb0c..b5221313f 100644 --- a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/yaml/YamlTypeIT.java +++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/yaml/YamlTypeIT.java @@ -271,13 +271,13 @@ public void useDoubleNumbersFalseCausesPrimitiveNumbersToBecomeFloats() throws C } @Test - public void unionTypesChooseFirstTypePresent() throws ClassNotFoundException, SecurityException, NoSuchMethodException { + public void unionTypesChooseFirstTypePresent() throws ReflectiveOperationException { Class classWithUnionProperties = schemaRule.generateAndCompile("/schema/yaml/type/unionTypes.yaml", "com.example", config("sourceType", "yamlschema")).loadClass("com.example.UnionTypes"); - Method booleanGetter = classWithUnionProperties.getMethod("getBooleanProperty"); + Method nullTypeGetter = classWithUnionProperties.getMethod("getNullProperty"); - assertThat(booleanGetter.getReturnType().getName(), is("java.lang.Boolean")); + assertThat(nullTypeGetter.getReturnType().getName(), is("java.lang.Object")); Method stringGetter = classWithUnionProperties.getMethod("getStringProperty"); @@ -286,6 +286,20 @@ public void unionTypesChooseFirstTypePresent() throws ClassNotFoundException, Se Method integerGetter = classWithUnionProperties.getMethod("getIntegerProperty"); assertThat(integerGetter.getReturnType().getName(), is("java.lang.Integer")); + + Method booleanGetter = classWithUnionProperties.getMethod("getBooleanProperty"); + assertThat(booleanGetter.getReturnType().getName(), is("java.lang.Boolean")); + } + + @Test + public void mixedUnionTypesReturnObject() throws ReflectiveOperationException { + Class classWithMixedUnionProperties = schemaRule.generateAndCompile("/schema/yaml/type/mixedUnionTypes.yaml", "com.example", config("sourceType", "yamlschema")).loadClass("com.example.MixedUnionTypes"); + + Method mixedTypesGetter = classWithMixedUnionProperties.getMethod("getMixedTypesProperty"); + assertThat(mixedTypesGetter.getReturnType().getName(), is("java.lang.Object")); + + Method mixedTypesWithNullGetter = classWithMixedUnionProperties.getMethod("getMixedTypesWithNullProperty"); + assertThat(mixedTypesWithNullGetter.getReturnType().getName(), is("java.lang.Object")); } @SuppressWarnings("rawtypes") diff --git a/jsonschema2pojo-integration-tests/src/test/resources/schema/type/mixedUnionTypes.json b/jsonschema2pojo-integration-tests/src/test/resources/schema/type/mixedUnionTypes.json new file mode 100644 index 000000000..9557b5685 --- /dev/null +++ b/jsonschema2pojo-integration-tests/src/test/resources/schema/type/mixedUnionTypes.json @@ -0,0 +1,11 @@ +{ + "type" : "object", + "properties" : { + "mixedTypesProperty": { + "type": ["boolean", "string"] + }, + "mixedTypesWithNullProperty": { + "type": ["null", "string", "boolean"] + } + } +} \ No newline at end of file diff --git a/jsonschema2pojo-integration-tests/src/test/resources/schema/type/unionTypes.json b/jsonschema2pojo-integration-tests/src/test/resources/schema/type/unionTypes.json index 0362ee57d..0dbaaa5b6 100644 --- a/jsonschema2pojo-integration-tests/src/test/resources/schema/type/unionTypes.json +++ b/jsonschema2pojo-integration-tests/src/test/resources/schema/type/unionTypes.json @@ -1,14 +1,17 @@ { "type" : "object", "properties" : { - "booleanProperty" : { - "type" : ["boolean", "string"] + "nullProperty" : { + "type" : ["null"] }, "stringProperty" : { "type" : ["string"] }, "integerProperty" : { "type" : ["integer", "null"] + }, + "booleanProperty": { + "type" : ["null", "boolean"] } } } \ No newline at end of file diff --git a/jsonschema2pojo-integration-tests/src/test/resources/schema/yaml/type/mixedUnionTypes.yaml b/jsonschema2pojo-integration-tests/src/test/resources/schema/yaml/type/mixedUnionTypes.yaml new file mode 100644 index 000000000..ec3ab285f --- /dev/null +++ b/jsonschema2pojo-integration-tests/src/test/resources/schema/yaml/type/mixedUnionTypes.yaml @@ -0,0 +1,11 @@ +properties: + mixedTypesProperty: + type: + - boolean + - string + mixedTypesWithNullProperty: + type: + - 'null' + - string + - boolean +type: object diff --git a/jsonschema2pojo-integration-tests/src/test/resources/schema/yaml/type/unionTypes.yaml b/jsonschema2pojo-integration-tests/src/test/resources/schema/yaml/type/unionTypes.yaml index 2f5011166..cfbf0d634 100644 --- a/jsonschema2pojo-integration-tests/src/test/resources/schema/yaml/type/unionTypes.yaml +++ b/jsonschema2pojo-integration-tests/src/test/resources/schema/yaml/type/unionTypes.yaml @@ -1,8 +1,7 @@ properties: - booleanProperty: + nullProperty: type: - - boolean - - string + - 'null' integerProperty: type: - integer @@ -10,4 +9,8 @@ properties: stringProperty: type: - string + booleanProperty: + type: + - 'null' + - boolean type: object