diff --git a/vertx-oracle-client/src/main/java/io/vertx/oracleclient/impl/Helper.java b/vertx-oracle-client/src/main/java/io/vertx/oracleclient/impl/Helper.java index d50a1c463..be607161e 100644 --- a/vertx-oracle-client/src/main/java/io/vertx/oracleclient/impl/Helper.java +++ b/vertx-oracle-client/src/main/java/io/vertx/oracleclient/impl/Helper.java @@ -167,26 +167,26 @@ public static Object convertSqlValue(Object value) throws SQLException { } if (value instanceof OracleJsonValue) { - return convertOracleJsonValue((OracleJsonValue) value); + return convertOracleJsonValue((OracleJsonValue) value, true); } // fallback to String return value.toString(); } - private static Object convertOracleJsonValue(OracleJsonValue oracleJson) { + private static Object convertOracleJsonValue(OracleJsonValue oracleJson, boolean topLevel) { if (oracleJson instanceof OracleJsonObject) { OracleJsonObject obj = (OracleJsonObject) oracleJson; Map map = new LinkedHashMap<>(obj.size()); for (Map.Entry entry : obj.entrySet()) { - map.put(entry.getKey(), convertOracleJsonValue(entry.getValue())); + map.put(entry.getKey(), convertOracleJsonValue(entry.getValue(), false)); } return new JsonObject(map); } else if (oracleJson instanceof OracleJsonArray) { OracleJsonArray arr = (OracleJsonArray) oracleJson; List list = new ArrayList<>(arr.size()); for (OracleJsonValue element : arr) { - list.add(convertOracleJsonValue(element)); + list.add(convertOracleJsonValue(element, false)); } return new JsonArray(list); } else if (oracleJson instanceof OracleJsonString) { @@ -204,7 +204,7 @@ private static Object convertOracleJsonValue(OracleJsonValue oracleJson) { case FALSE: return Boolean.FALSE; case NULL: - return Tuple.JSON_NULL; + return topLevel ? Tuple.JSON_NULL : null; default: return null; } diff --git a/vertx-oracle-client/src/test/java/tests/oracleclient/OracleJsonDataTypeTest.java b/vertx-oracle-client/src/test/java/tests/oracleclient/OracleJsonDataTypeTest.java index a3eb8da5f..124da72e8 100644 --- a/vertx-oracle-client/src/test/java/tests/oracleclient/OracleJsonDataTypeTest.java +++ b/vertx-oracle-client/src/test/java/tests/oracleclient/OracleJsonDataTypeTest.java @@ -301,4 +301,31 @@ public void testInsertJsonBooleanWithSqlWorkaround(TestContext ctx) { ctx.assertEquals(Boolean.TRUE, rows.iterator().next().getJson(0)); })); } + + @Test + public void testDecodeNestedJsonNull(TestContext ctx) { + JsonObject expected = new JsonObject().put("key", (String) null); + pool.preparedQuery("INSERT INTO json_test (id, data) VALUES (?, ?)") + .execute(Tuple.of(50, expected)) + .compose(v -> pool.preparedQuery("SELECT data FROM json_test WHERE id = ?").execute(Tuple.of(50))) + .onComplete(ctx.asyncAssertSuccess(rows -> { + ctx.assertEquals(1, rows.size()); + Row row = rows.iterator().next(); + JsonObject result = row.getJsonObject(0); + ctx.assertTrue(result.containsKey("key")); + ctx.assertNull(result.getValue("key")); + })); + } + + @Test + public void testDecodeTopLevelJsonNull(TestContext ctx) { + pool.preparedQuery("INSERT INTO json_test (id, data) VALUES (?, ?)") + .execute(Tuple.of(51, Tuple.JSON_NULL)) + .compose(v -> pool.preparedQuery("SELECT data FROM json_test WHERE id = ?").execute(Tuple.of(51))) + .onComplete(ctx.asyncAssertSuccess(rows -> { + ctx.assertEquals(1, rows.size()); + Row row = rows.iterator().next(); + ctx.assertEquals(Tuple.JSON_NULL, row.getJson(0)); + })); + } }