From 91e2604dc5ae3ac2faaff0d03e84ab4d6a9f1c25 Mon Sep 17 00:00:00 2001 From: Michael Edgar Date: Thu, 4 Jul 2024 09:38:21 -0400 Subject: [PATCH] Improve parsing of strings to objects (examples, defaults) Signed-off-by: Michael Edgar --- .../smallrye/openapi/runtime/io/JsonIO.java | 27 ++++++++++---- .../scanner/StandaloneSchemaScanTest.java | 26 ++++++++++++++ ...mponents.schemas.exceptional-examples.json | 36 +++++++++++++++++++ 3 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 core/src/test/resources/io/smallrye/openapi/runtime/scanner/components.schemas.exceptional-examples.json diff --git a/core/src/main/java/io/smallrye/openapi/runtime/io/JsonIO.java b/core/src/main/java/io/smallrye/openapi/runtime/io/JsonIO.java index 74e5649a1..223ed8e71 100644 --- a/core/src/main/java/io/smallrye/openapi/runtime/io/JsonIO.java +++ b/core/src/main/java/io/smallrye/openapi/runtime/io/JsonIO.java @@ -24,6 +24,10 @@ public static JsonIO newI return jackson; } + private boolean wrapped(String value, String prefix, String suffix) { + return value.startsWith(prefix) && value.endsWith(suffix); + } + default Object parseValue(String value) { if (value == null || value.isEmpty()) { return null; @@ -32,10 +36,19 @@ default Object parseValue(String value) { String trimmedValue = value.trim(); switch (trimmedValue.charAt(0)) { - case '{': /* JSON Object */ - case '[': /* JSON Array */ - case '-': /* JSON Negative Number */ - case '0': /* JSON Numbers */ + case '{': + case '[': + if (wrapped(trimmedValue, "{", "}") || wrapped(trimmedValue, "[", "]")) { + /* Looks like a JSON Object or Array */ + try { + return fromJson(fromString(trimmedValue, Format.JSON)); + } catch (Exception e) { + IoLogging.logger.unparseableJson(trimmedValue); + } + } + break; + case '-': /* Negative Number */ + case '0': /* Numbers */ case '1': case '2': case '3': @@ -46,11 +59,11 @@ default Object parseValue(String value) { case '8': case '9': try { - return fromJson(fromString(trimmedValue, Format.JSON)); - } catch (Exception e) { + return new BigDecimal(trimmedValue); + } catch (NumberFormatException e) { IoLogging.logger.unparseableJson(trimmedValue); - break; } + break; case 't': return "true".equals(trimmedValue) ? Boolean.TRUE : value; case 'f': diff --git a/core/src/test/java/io/smallrye/openapi/runtime/scanner/StandaloneSchemaScanTest.java b/core/src/test/java/io/smallrye/openapi/runtime/scanner/StandaloneSchemaScanTest.java index 536fb8834..53009b282 100644 --- a/core/src/test/java/io/smallrye/openapi/runtime/scanner/StandaloneSchemaScanTest.java +++ b/core/src/test/java/io/smallrye/openapi/runtime/scanner/StandaloneSchemaScanTest.java @@ -763,4 +763,30 @@ public String getWo() { assertJsonEquals("components.schemas.jackson-property-access.json", Bean.class); } + + @Test + void testExceptionalExampleParsing() throws IOException, JSONException { + @Schema(name = "Bean") + class Bean { + @Schema(example = "{ Looks like object, but invalid }") + public Object property1; + @Schema(example = "{ \"key\": \"object end missing\"") + public Object property2; + @Schema(example = "[ Looks like array, but invalid ]") + public Object property3; + @Schema(example = "[ \"array end missing\"") + public Object property4; + @Schema(example = "trick") // not Boolean.TRUE + public Object property5; + @Schema(example = "fake") // not Boolean.FALSE + public Object property6; + @Schema(example = "1046\n1049\n1051") // not a number + public Object property7; + @Schema(example = "") // empty + public Object property8; + + } + + assertJsonEquals("components.schemas.exceptional-examples.json", Bean.class); + } } diff --git a/core/src/test/resources/io/smallrye/openapi/runtime/scanner/components.schemas.exceptional-examples.json b/core/src/test/resources/io/smallrye/openapi/runtime/scanner/components.schemas.exceptional-examples.json new file mode 100644 index 000000000..29892de7f --- /dev/null +++ b/core/src/test/resources/io/smallrye/openapi/runtime/scanner/components.schemas.exceptional-examples.json @@ -0,0 +1,36 @@ +{ + "openapi" : "3.0.3", + "components" : { + "schemas" : { + "Bean" : { + "type" : "object", + "properties" : { + "property1" : { + "example" : "{ Looks like object, but invalid }" + }, + "property2" : { + "example" : "{ \"key\": \"object end missing\"" + }, + "property3" : { + "example" : "[ Looks like array, but invalid ]" + }, + "property4" : { + "example" : "[ \"array end missing\"" + }, + "property5" : { + "example" : "trick" + }, + "property6" : { + "example" : "fake" + }, + "property7" : { + "example" : "1046\n1049\n1051" + }, + "property8" : { + "example" : "" + } + } + } + } + } +}