forked from opensearch-project/sql
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
json-valid PPL function (opensearch-project#3230)
Add json-valid PPL function (opensearch-project#3230) --------- Signed-off-by: Kenrick Yap <[email protected]> Signed-off-by: Kenrick Yap <[email protected]> Signed-off-by: kenrickyap <[email protected]> Signed-off-by: Andrew Carbonetto <[email protected]> Co-authored-by: Kenrick Yap <[email protected]> Co-authored-by: Andrew Carbonetto <[email protected]>
- Loading branch information
1 parent
e7be8ca
commit d5806cc
Showing
19 changed files
with
279 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
core/src/main/java/org/opensearch/sql/expression/json/JsonFunctions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.sql.expression.json; | ||
|
||
import static org.opensearch.sql.data.type.ExprCoreType.BOOLEAN; | ||
import static org.opensearch.sql.data.type.ExprCoreType.STRING; | ||
import static org.opensearch.sql.expression.function.FunctionDSL.define; | ||
import static org.opensearch.sql.expression.function.FunctionDSL.impl; | ||
|
||
import lombok.experimental.UtilityClass; | ||
import org.opensearch.sql.expression.function.BuiltinFunctionName; | ||
import org.opensearch.sql.expression.function.BuiltinFunctionRepository; | ||
import org.opensearch.sql.expression.function.DefaultFunctionResolver; | ||
import org.opensearch.sql.utils.JsonUtils; | ||
|
||
@UtilityClass | ||
public class JsonFunctions { | ||
public void register(BuiltinFunctionRepository repository) { | ||
repository.register(jsonValid()); | ||
} | ||
|
||
private DefaultFunctionResolver jsonValid() { | ||
return define( | ||
BuiltinFunctionName.JSON_VALID.getName(), impl(JsonUtils::isValidJson, BOOLEAN, STRING)); | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
core/src/main/java/org/opensearch/sql/utils/JsonUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package org.opensearch.sql.utils; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import lombok.experimental.UtilityClass; | ||
import org.opensearch.sql.data.model.ExprValue; | ||
import org.opensearch.sql.data.model.ExprValueUtils; | ||
|
||
@UtilityClass | ||
public class JsonUtils { | ||
/** | ||
* Checks if given JSON string can be parsed as valid JSON. | ||
* | ||
* @param jsonExprValue JSON string (e.g. "{\"hello\": \"world\"}"). | ||
* @return true if the string can be parsed as valid JSON, else false. | ||
*/ | ||
public static ExprValue isValidJson(ExprValue jsonExprValue) { | ||
ObjectMapper objectMapper = new ObjectMapper(); | ||
|
||
if (jsonExprValue.isNull() || jsonExprValue.isMissing()) { | ||
return ExprValueUtils.LITERAL_FALSE; | ||
} | ||
|
||
try { | ||
objectMapper.readTree(jsonExprValue.stringValue()); | ||
return ExprValueUtils.LITERAL_TRUE; | ||
} catch (JsonProcessingException e) { | ||
return ExprValueUtils.LITERAL_FALSE; | ||
} | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
core/src/test/java/org/opensearch/sql/expression/json/JsonFunctionsTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.sql.expression.json; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
import static org.opensearch.sql.data.model.ExprValueUtils.LITERAL_FALSE; | ||
import static org.opensearch.sql.data.model.ExprValueUtils.LITERAL_MISSING; | ||
import static org.opensearch.sql.data.model.ExprValueUtils.LITERAL_NULL; | ||
import static org.opensearch.sql.data.model.ExprValueUtils.LITERAL_TRUE; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.opensearch.sql.data.model.ExprValue; | ||
import org.opensearch.sql.data.model.ExprValueUtils; | ||
import org.opensearch.sql.exception.ExpressionEvaluationException; | ||
import org.opensearch.sql.expression.DSL; | ||
import org.opensearch.sql.expression.FunctionExpression; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
public class JsonFunctionsTest { | ||
private static final ExprValue JsonNestedObject = | ||
ExprValueUtils.stringValue("{\"a\":\"1\",\"b\":{\"c\":\"2\",\"d\":\"3\"}}"); | ||
private static final ExprValue JsonObject = | ||
ExprValueUtils.stringValue("{\"a\":\"1\",\"b\":\"2\"}"); | ||
private static final ExprValue JsonArray = ExprValueUtils.stringValue("[1, 2, 3, 4]"); | ||
private static final ExprValue JsonScalarString = ExprValueUtils.stringValue("\"abc\""); | ||
private static final ExprValue JsonEmptyString = ExprValueUtils.stringValue(""); | ||
private static final ExprValue JsonInvalidObject = | ||
ExprValueUtils.stringValue("{\"invalid\":\"json\", \"string\"}"); | ||
private static final ExprValue JsonInvalidScalar = ExprValueUtils.stringValue("abc"); | ||
|
||
@Test | ||
public void json_valid_returns_false() { | ||
assertEquals(LITERAL_FALSE, execute(JsonInvalidObject)); | ||
assertEquals(LITERAL_FALSE, execute(JsonInvalidScalar)); | ||
assertEquals(LITERAL_FALSE, execute(LITERAL_NULL)); | ||
assertEquals(LITERAL_FALSE, execute(LITERAL_MISSING)); | ||
} | ||
|
||
@Test | ||
public void json_valid_throws_ExpressionEvaluationException() { | ||
assertThrows( | ||
ExpressionEvaluationException.class, () -> execute(ExprValueUtils.booleanValue(true))); | ||
} | ||
|
||
@Test | ||
public void json_valid_returns_true() { | ||
assertEquals(LITERAL_TRUE, execute(JsonNestedObject)); | ||
assertEquals(LITERAL_TRUE, execute(JsonObject)); | ||
assertEquals(LITERAL_TRUE, execute(JsonArray)); | ||
assertEquals(LITERAL_TRUE, execute(JsonScalarString)); | ||
assertEquals(LITERAL_TRUE, execute(JsonEmptyString)); | ||
} | ||
|
||
private ExprValue execute(ExprValue jsonString) { | ||
FunctionExpression exp = DSL.jsonValid(DSL.literal(jsonString)); | ||
return exp.valueOf(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
==================== | ||
JSON Functions | ||
==================== | ||
|
||
.. rubric:: Table of contents | ||
|
||
.. contents:: | ||
:local: | ||
:depth: 1 | ||
|
||
JSON_VALID | ||
---------- | ||
|
||
Description | ||
>>>>>>>>>>> | ||
|
||
Usage: `json_valid(json_string)` checks if `json_string` is a valid JSON-encoded string. | ||
|
||
Argument type: STRING | ||
|
||
Return type: BOOLEAN | ||
|
||
Example:: | ||
|
||
> source=json_test | eval is_valid = json_valid(json_string) | fields test_name, json_string, is_valid | ||
fetched rows / total rows = 6/6 | ||
+---------------------+---------------------------------+----------+ | ||
| test_name | json_string | is_valid | | ||
|---------------------|---------------------------------|----------| | ||
| json nested object | {"a":"1","b":{"c":"2","d":"3"}} | True | | ||
| json object | {"a":"1","b":"2"} | True | | ||
| json array | [1, 2, 3, 4] | True | | ||
| json scalar string | "abc" | True | | ||
| json empty string | | True | | ||
| json invalid object | {"invalid":"json", "string"} | False | | ||
+---------------------+---------------------------------+----------+ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{"test_name":"json nested object", "json_string":"{\"a\":\"1\",\"b\":{\"c\":\"2\",\"d\":\"3\"}}"} | ||
{"test_name":"json object", "json_string":"{\"a\":\"1\",\"b\":\"2\"}"} | ||
{"test_name":"json array", "json_string":"[1, 2, 3, 4]"} | ||
{"test_name":"json scalar string", "json_string":"\"abc\""} | ||
{"test_name":"json empty string","json_string":""} | ||
{"test_name":"json invalid object", "json_string":"{\"invalid\":\"json\", \"string\"}"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
integ-test/src/test/java/org/opensearch/sql/ppl/JsonFunctionsIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.sql.ppl; | ||
|
||
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_JSON_TEST; | ||
import static org.opensearch.sql.util.MatcherUtils.rows; | ||
import static org.opensearch.sql.util.MatcherUtils.schema; | ||
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows; | ||
import static org.opensearch.sql.util.MatcherUtils.verifySchema; | ||
|
||
import java.io.IOException; | ||
import org.json.JSONObject; | ||
import org.junit.jupiter.api.Test; | ||
|
||
public class JsonFunctionsIT extends PPLIntegTestCase { | ||
@Override | ||
public void init() throws IOException { | ||
loadIndex(Index.JSON_TEST); | ||
} | ||
|
||
@Test | ||
public void test_json_valid() throws IOException { | ||
JSONObject result; | ||
|
||
result = | ||
executeQuery( | ||
String.format( | ||
"source=%s | where json_valid(json_string) | fields test_name", | ||
TEST_INDEX_JSON_TEST)); | ||
verifySchema(result, schema("test_name", null, "string")); | ||
verifyDataRows( | ||
result, | ||
rows("json nested object"), | ||
rows("json object"), | ||
rows("json array"), | ||
rows("json scalar string"), | ||
rows("json empty string")); | ||
} | ||
|
||
@Test | ||
public void test_not_json_valid() throws IOException { | ||
JSONObject result; | ||
|
||
result = | ||
executeQuery( | ||
String.format( | ||
"source=%s | where not json_valid(json_string) | fields test_name", | ||
TEST_INDEX_JSON_TEST)); | ||
verifySchema(result, schema("test_name", null, "string")); | ||
verifyDataRows(result, rows("json invalid object"), rows("json null")); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
integ-test/src/test/resources/indexDefinitions/json_test_index_mapping.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"mappings": { | ||
"properties": { | ||
"test_name": { | ||
"type": "keyword" | ||
}, | ||
"json_string": { | ||
"type": "keyword" | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{"index":{"_id":"0"}} | ||
{"test_name":"json nested object", "json_string":"{\"a\":\"1\",\"b\":{\"c\":\"2\",\"d\":\"3\"}}"} | ||
{"index":{"_id":"1"}} | ||
{"test_name":"json object", "json_string":"{\"a\":\"1\",\"b\":\"2\"}"} | ||
{"index":{"_id":"2"}} | ||
{"test_name":"json array", "json_string":"[1, 2, 3, 4]"} | ||
{"index":{"_id":"3"}} | ||
{"test_name":"json scalar string", "json_string":"\"abc\""} | ||
{"index":{"_id":"4"}} | ||
{"test_name":"json empty string","json_string":""} | ||
{"index":{"_id":"5"}} | ||
{"test_name":"json invalid object", "json_string":"{\"invalid\":\"json\", \"string\"}"} | ||
{"index":{"_id":"6"}} | ||
{"test_name":"json null", "json_string":null} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.