This is an automated email from the ASF dual-hosted git repository.
xiangfu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push:
new de8fa0beb6 Support jsonKeyValueArrayToMap function (#15352)
de8fa0beb6 is described below
commit de8fa0beb61cd91bbe5761bcc4a21efc65f6f0c8
Author: Xiang Fu <[email protected]>
AuthorDate: Wed Mar 26 14:42:07 2025 -0700
Support jsonKeyValueArrayToMap function (#15352)
---
.../common/function/scalar/JsonFunctions.java | 58 ++++++++++++++++++++++
.../pinot/common/function/JsonFunctionsTest.java | 31 ++++++++++++
2 files changed, 89 insertions(+)
diff --git
a/pinot-common/src/main/java/org/apache/pinot/common/function/scalar/JsonFunctions.java
b/pinot-common/src/main/java/org/apache/pinot/common/function/scalar/JsonFunctions.java
index 2810419f95..6e93b11e73 100644
---
a/pinot-common/src/main/java/org/apache/pinot/common/function/scalar/JsonFunctions.java
+++
b/pinot-common/src/main/java/org/apache/pinot/common/function/scalar/JsonFunctions.java
@@ -19,6 +19,8 @@
package org.apache.pinot.common.function.scalar;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.annotations.VisibleForTesting;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
@@ -226,6 +228,62 @@ public class JsonFunctions {
}
}
+ /**
+ * Extract an array of key-value maps to a map.
+ * E.g. input: [{"key": "k1", "value": "v1"}, {"key": "k2", "value": "v2"},
{"key": "k3", "value": "v3"}]
+ * output: {"k1": "v1", "k2": "v2", "k3": "v3"}
+ */
+ @ScalarFunction
+ public static Object jsonKeyValueArrayToMap(Object keyValueArray) {
+ return jsonKeyValueArrayToMap(keyValueArray, "key", "value");
+ }
+
+ @ScalarFunction
+ public static Object jsonKeyValueArrayToMap(Object keyValueArray, String
keyColumnName, String valueColumnName) {
+ Map<String, String> result = new java.util.HashMap<>();
+ if (keyValueArray instanceof Object[]) {
+ Object[] array = (Object[]) keyValueArray;
+ for (Object obj : array) {
+ setValuesToMap(keyColumnName, valueColumnName, obj, result);
+ }
+ } else if (keyValueArray instanceof List) {
+ List<Object> list = (List<Object>) keyValueArray;
+ for (Object obj : list) {
+ setValuesToMap(keyColumnName, valueColumnName, obj, result);
+ }
+ } else {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode arrayNode;
+ try {
+ arrayNode = mapper.readTree(keyValueArray.toString());
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ for (int i = 0; i < arrayNode.size(); i++) {
+ JsonNode node = arrayNode.get(i);
+ result.put(node.get(keyColumnName).asText(),
node.get(valueColumnName).asText());
+ }
+ }
+ return result;
+ }
+
+ private static void setValuesToMap(String keyColumnName, String
valueColumnName, Object obj,
+ Map<String, String> result) {
+ if (obj instanceof Map) {
+ Map<String, String> objMap = (Map) obj;
+ result.put(objMap.get(keyColumnName), objMap.get(valueColumnName));
+ } else {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode mapNode;
+ try {
+ mapNode = mapper.readTree(obj.toString());
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ result.put(mapNode.get(keyColumnName).asText(),
mapNode.get(valueColumnName).asText());
+ }
+ }
+
@VisibleForTesting
static class ArrayAwareJacksonJsonProvider extends JacksonJsonProvider {
@Override
diff --git
a/pinot-common/src/test/java/org/apache/pinot/common/function/JsonFunctionsTest.java
b/pinot-common/src/test/java/org/apache/pinot/common/function/JsonFunctionsTest.java
index 8b28af5fea..c374cfbf1f 100644
---
a/pinot-common/src/test/java/org/apache/pinot/common/function/JsonFunctionsTest.java
+++
b/pinot-common/src/test/java/org/apache/pinot/common/function/JsonFunctionsTest.java
@@ -401,4 +401,35 @@ public class JsonFunctionsTest {
assertFalse(JsonFunctions.jsonPathExists(null, "$.[*].name"));
assertFalse(JsonFunctions.jsonPathExists(null, null));
}
+
+ @Test
+ public void testJsonKeyValueArrayToMap() {
+ String jsonString = "["
+ + "{\"key\": \"k1\", \"value\": \"v1\"}, "
+ + "{\"key\": \"k2\", \"value\": \"v2\"}, "
+ + "{\"key\": \"k3\", \"value\": \"v3\"}, "
+ + "{\"key\": \"k4\", \"value\": \"v4\"}, "
+ + "{\"key\": \"k5\", \"value\": \"v5\"}"
+ + "]";
+ Map<String, Object> expected = ImmutableMap.of("k1", "v1", "k2", "v2",
"k3", "v3", "k4", "v4", "k5", "v5");
+ assertEquals(JsonFunctions.jsonKeyValueArrayToMap(jsonString), expected);
+
+ Object[] jsonArray = new Object[]{
+ "{\"key\": \"k1\", \"value\": \"v1\"}",
+ "{\"key\": \"k2\", \"value\": \"v2\"}",
+ "{\"key\": \"k3\", \"value\": \"v3\"}",
+ "{\"key\": \"k4\", \"value\": \"v4\"}",
+ "{\"key\": \"k5\", \"value\": \"v5\"}"
+ };
+ assertEquals(JsonFunctions.jsonKeyValueArrayToMap(jsonArray), expected);
+
+ List<Object> jsonList = ImmutableList.of(
+ "{\"key\": \"k1\", \"value\": \"v1\"}",
+ "{\"key\": \"k2\", \"value\": \"v2\"}",
+ "{\"key\": \"k3\", \"value\": \"v3\"}",
+ "{\"key\": \"k4\", \"value\": \"v4\"}",
+ "{\"key\": \"k5\", \"value\": \"v5\"}"
+ );
+ assertEquals(JsonFunctions.jsonKeyValueArrayToMap(jsonList), expected);
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]