jerqi commented on code in PR #7690:
URL: https://github.com/apache/gravitino/pull/7690#discussion_r2259828318


##########
common/src/main/java/org/apache/gravitino/json/JsonUtils.java:
##########
@@ -1343,6 +1349,94 @@ public Expression deserialize(JsonParser p, 
DeserializationContext ctxt) throws
     }
   }
 
+  /** Custom JSON deserializer for StatisticValue objects. */
+  public static class StatisticValueDeserializer extends 
JsonDeserializer<StatisticValue> {
+    @Override
+    public StatisticValue<?> deserialize(JsonParser p, DeserializationContext 
ctxt)
+        throws IOException {
+      JsonNode node = p.getCodec().readTree(p);
+      return getStatisticValue(node);
+    }
+  }
+
+  private static StatisticValue<?> getStatisticValue(JsonNode node) throws 
IOException {
+    Preconditions.checkArgument(
+        node != null && !node.isNull(), "Cannot parse statistic value from 
invalid JSON: %s", node);
+    if (node.isIntegralNumber()) {
+      return StatisticValues.longValue(node.asLong());
+    } else if (node.isFloatingPointNumber()) {
+      return StatisticValues.doubleValue(node.asDouble());
+    } else if (node.isTextual()) {
+      return StatisticValues.stringValue(node.asText());
+    } else if (node.isBoolean()) {
+      return StatisticValues.booleanValue(node.asBoolean());
+    } else if (node.isArray()) {
+      ArrayNode arrayNode = (ArrayNode) node;
+      List<StatisticValue<Object>> values = 
Lists.newArrayListWithCapacity(arrayNode.size());
+      for (JsonNode arrayElement : arrayNode) {
+        StatisticValue<?> value = getStatisticValue(arrayElement);
+        if (value != null) {
+          values.add((StatisticValue<Object>) value);
+        }
+      }
+      return StatisticValues.listValue(values);
+    } else if (node.isObject()) {
+      ObjectNode objectNode = (ObjectNode) node;
+      Map<String, StatisticValue<?>> map = Maps.newHashMap();
+      objectNode
+          .fields()
+          .forEachRemaining(
+              entry -> {
+                try {
+                  StatisticValue<?> value = 
getStatisticValue(entry.getValue());
+                  if (value != null) {
+                    map.put(entry.getKey(), value);
+                  }
+                } catch (IOException e) {
+                  throw new RuntimeException(e);
+                }
+              });
+      return StatisticValues.objectValue(map);
+    } else {
+      throw new UnsupportedEncodingException(
+          String.format("Don't support json node type %s", 
node.getNodeType()));
+    }
+  }
+
+  /** Custom JSON serializer for StatisticValue objects. */
+  public static class StatisticValueSerializer extends 
JsonSerializer<StatisticValue> {
+
+    @Override
+    public void serialize(StatisticValue value, JsonGenerator gen, 
SerializerProvider serializers)
+        throws IOException {
+      if (value.dataType().name() == Type.Name.BOOLEAN) {
+        gen.writeBoolean((Boolean) value.value());
+      } else if (value.dataType().name() == Type.Name.STRING) {
+        gen.writeString((String) value.value());
+      } else if (value.dataType().name() == Type.Name.DOUBLE) {
+        gen.writeNumber((Double) value.value());
+      } else if (value.dataType().name() == Type.Name.LONG) {
+        gen.writeNumber((Long) value.value());
+      } else if (value.dataType().name() == Type.Name.LIST) {
+        gen.writeStartArray();
+        for (StatisticValue<?> element : (List<StatisticValue<?>>) 
value.value()) {
+          serialize(element, gen, serializers);
+        }
+        gen.writeEndArray();
+      } else if (value.dataType().name() == Type.Name.STRUCT) {
+        gen.writeStartObject();
+        for (Map.Entry<String, StatisticValue<?>> entry :
+            ((Map<String, StatisticValue<?>>) value.value()).entrySet()) {
+          gen.writeFieldName(entry.getKey());
+          serialize(entry.getValue(), gen, serializers);
+        }
+        gen.writeEndObject();
+      } else {
+        throw new IOException("Unsupported statistic value type: " + 
value.dataType());
+      }
+    }
+  }

Review Comment:
   Literal serializer format is as follows:
   ``` 
   {
           "type": "literal",
           "dataType": "null",
           "value": "1"
    }
   ```
   value will always be a string. I don't prefer this style.
   Now serialize result will be simple kv. k1, k2 represents statistic name. 
   Option 1:
   ```
   {
      "k1": 1,
       "k2": "string"
   }
   ```
   Another method is put dataType in the object
   Option 2:
   ```
   {
      "k1": {
           "dataType": "LONG",
           "value": 1
       },
         "k2": {
           "dataType": "STRING",
           "value": "string"
       }
   }
   ```
   Actually, the json value have some simple type. The type information is 
rebundant. I think it's more clear and easy to use. 
   But if you think json type didn't give enough constraint, although I think 
statistic usage doesn't need such strong constraint. I can choose option2.



-- 
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]

Reply via email to