fhueske commented on code in PR #24967:
URL: https://github.com/apache/flink/pull/24967#discussion_r1669010333
##########
docs/data/sql_functions.yml:
##########
@@ -377,6 +377,12 @@ string:
- sql: SUBSTR(string, integer1[, integer2])
table: STRING.substr(INTEGER1[, INTEGER2])
description: Returns a substring of string starting from position integer1
with length integer2 (to the end by default).
+ - sql: JSON_QUOTE(string)
+ table: STRING.JsonQuote()
+ description: Quotes a string as a JSON value by wrapping it with double
quote characters, escaping interior quote and special characters ('"', '\',
'/', 'b', 'f', 'n', 'r', 't'), and returning the result as a string. If the
argument is NULL, the function returns NULL.
+ - sql: JSON_UNQUOTE(string)
+ table: STRING.JsonUnquote()
+ description: Unquotes JSON value, escapes special characters ('"', '\',
'/', 'b', 'f', 'n', 'r', 't', 'u' hex hex hex hex), and returns the result as a
string. If the argument is NULL, returns NULL. If the value starts and ends
with double quotes but is not a valid JSON string literal, the value is passed
through unmodified.
Review Comment:
```suggestion
description: Unquotes JSON value, unescapes escaped special characters
('"', '\', '/', 'b', 'f', 'n', 'r', 't', 'u' hex hex hex hex), and returns the
result as a string. If the argument is NULL, returns NULL. If the value starts
and ends with double quotes but is not a valid JSON string literal, the value
is passed through unmodified.
```
we are unescaping (previously) escaped characters, right?
##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/JsonFunctionsITCase.java:
##########
@@ -794,6 +795,196 @@ private static List<TestSetSpec> jsonObjectSpec() {
STRING().notNull()));
}
+ private static List<TestSetSpec> jsonQuoteSpec() {
+
+ return Arrays.asList(
+ TestSetSpec.forFunction(BuiltInFunctionDefinitions.JSON_QUOTE)
+ .onFieldsWithData(0)
+ .testResult(
+ nullOf(STRING()).jsonQuote(),
+ "JSON_QUOTE(CAST(NULL AS STRING))",
+ null,
+ STRING().nullable()),
+ TestSetSpec.forFunction(BuiltInFunctionDefinitions.JSON_QUOTE)
+ .onFieldsWithData(
+ "V",
+ "\"null\"",
+ "[1, 2, 3]",
+ "This is a \t test \n with special characters:
\" \\ \b \f \r \u0041",
+ "\"kv_pair_test\": \"\\b\\f\\r\"",
+ "\ttab and fwd slash /",
+ "this will not be quoted \\u006z",
+ "this will be quoted ≠",
+ null)
+ .andDataTypes(
+ STRING().notNull(),
+ STRING().notNull(),
+ STRING().notNull(),
+ STRING().notNull(),
+ STRING().notNull(),
+ STRING().notNull(),
+ STRING().notNull(),
+ STRING().notNull(),
+ STRING().nullable())
+ .testResult(
+ $("f0").jsonQuote(), "JSON_QUOTE(f0)",
"\"V\"", STRING().notNull())
+ .testResult(
+ $("f1").jsonQuote(),
+ "JSON_QUOTE(f1)",
+ "\"\\\"null\\\"\"",
+ STRING().notNull())
+ .testResult(
+ $("f2").jsonQuote(),
+ "JSON_QUOTE(f2)",
+ "\"[1, 2, 3]\"",
+ STRING().notNull())
+ .testResult(
+ $("f3").jsonQuote(),
+ "JSON_QUOTE(f3)",
+ "\"This is a \\t test \\n with special
characters: \\\" \\\\ \\b \\f \\r A\"",
+ STRING().notNull())
+ .testResult(
+ $("f4").jsonQuote(),
+ "JSON_QUOTE(f4)",
+ "\"\\\"kv_pair_test\\\":
\\\"\\\\b\\\\f\\\\r\\\"\"",
+ STRING().notNull())
+ .testResult(
+ $("f5").jsonQuote(),
+ "JSON_QUOTE(f5)",
+ "\"\\ttab and fwd slash \\/\"",
+ STRING().notNull())
+ .testResult(
+ $("f6").jsonQuote(),
+ "JSON_QUOTE(f6)",
+ "\"this will not be quoted \\\\u006z\"",
+ STRING().notNull())
+ .testResult(
+ $("f7").jsonQuote(),
+ "JSON_QUOTE(f7)",
+ "\"this will be quoted \\u2260\"",
+ STRING().notNull())
+ .testResult(
+ $("f8").jsonQuote(), "JSON_QUOTE(f8)", null,
STRING().nullable()));
+ }
+
+ private static List<TestSetSpec> jsonUnquoteSpec() {
+
+ return Arrays.asList(
+
TestSetSpec.forFunction(BuiltInFunctionDefinitions.JSON_UNQUOTE)
+ .onFieldsWithData(0)
+ .testResult(
+ nullOf(STRING()).jsonQuote(),
+ "JSON_UNQUOTE(CAST(NULL AS STRING))",
+ null,
+ STRING().nullable()),
+
TestSetSpec.forFunction(BuiltInFunctionDefinitions.JSON_UNQUOTE)
Review Comment:
can we split the TestSetSpec into two specs, one with valid Json input and
the other with invalid (for which the input is returned)?
##########
flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/ScalarFunctionsTest.scala:
##########
@@ -604,6 +604,49 @@ class ScalarFunctionsTest extends ScalarTypesTestBase {
"foothebar")
}
+ @Test
+ def testJsonQuote(): Unit = {
+ testSqlApi("JSON_QUOTE('null')", "\"null\"")
+ testSqlApi("JSON_QUOTE('\"null\"')", "\"\\\"null\\\"\"")
+ testSqlApi("JSON_QUOTE('[1,2,3]')", "\"[1,2,3]\"")
+ testSqlApi("JSON_UNQUOTE(JSON_QUOTE('[1,2,3]'))", "[1,2,3]")
+ testSqlApi(
+ "JSON_QUOTE('This is a \\t test \\n with special characters: \" \\ \\b
\\f \\r \\u0041')",
+ "\"This is a \\\\t test \\\\n with special characters: \\\" \\\\ \\\\b
\\\\f \\\\r \\\\u0041\""
+ )
+ testSqlApi(
+ "JSON_QUOTE('\"special\": \"\\b\\f\\r\"')",
+ "\"\\\"special\\\": \\\"\\\\b\\\\f\\\\r\\\"\"")
+ testSqlApi(
+ "JSON_QUOTE('skipping backslash \')",
+ "\"skipping backslash \""
+ )
+ testSqlApi(
+ "JSON_QUOTE('this will be quoted ≠')",
+ "\"this will be quoted \\u2260\""
+ )
+ }
+
+ @Test
+ def testJsonUnquote(): Unit = {
Review Comment:
Add some test cases with invalid JSON input?
##########
flink-python/pyflink/table/expression.py:
##########
@@ -1954,6 +1956,25 @@ def json_query(self, path: str,
wrapping_behavior=JsonQueryWrapper.WITHOUT_ARRAY
on_empty._to_j_json_query_on_error_or_empty(),
on_error._to_j_json_query_on_error_or_empty())
+ def json_quote(self) -> 'Expression':
+ """
+ Quotes a string as a JSON value by wrapping it with double quote
characters,
+ escaping interior quote and special characters
+ ('"', '\', '/', 'b', 'f', 'n', 'r', 't'), and returning
+ the result as a string. If the argument is NULL, the function returns
NULL.
+ """
+ return _unary_op("jsonQuote")(self)
+
+ def json_unquote(self) -> 'Expression':
+ """
+ Unquotes JSON value, escapes spacial characters
Review Comment:
```suggestion
Unquotes JSON value, unescapes escaped spacial characters
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]