jackson-dataformats-binary
jackson-dataformats-binary copied to clipboard
Support work with com.google.protobuf.Struct
com.google.protobuf.Struct can be used to represent JsonObject.
What would be the benefit here?
We do not want to add more 3rd party dependencies, so I don't think this is something we should do.
I can convert it from and to json, so does the flatterBuffers.
package com.alibaba.ultramax.mtop.jsonpath;
/**
* TODO: description of this file
*
* @author 虎鸣, [email protected]
*/
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.flatbuffers.FlexBuffers;
import com.google.flatbuffers.FlexBuffersBuilder;
import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.Map;
public class FlexBuffersConverter {
/**
* 将 Jackson JsonNode 转换为 FlexBuffers 二进制。
*
* @param node 要转换的 JsonNode。
* @return 包含 FlexBuffers 数据的 ByteBuffer。
*/
public static ByteBuffer convert(JsonNode node) {
FlexBuffersBuilder builder = new FlexBuffersBuilder();
buildFromNode(builder, null, node);
return builder.finish();
}
/**
* 递归函数,根据 JsonNode 类型构建 FlexBuffers。
*
* @param builder FlexBuffers 构建器。
* @param node 当前要处理的 JsonNode。
*/
private static void buildFromNode(FlexBuffersBuilder builder, String key, JsonNode node) {
if (node == null || node.isNull()) {
builder.putNull(key);
} else if (node.isObject()) {
buildMapFromNode(builder, key, node);
} else if (node.isArray()) {
buildVectorFromNode(builder, key, node);
} else if (node.isTextual()) {
builder.putString(key, node.asText());
} else if (node.isIntegralNumber()) {
builder.putInt(key, node.asLong());
} else if (node.isFloatingPointNumber()) {
builder.putFloat(key, node.asDouble());
} else if (node.isBoolean()) {
builder.putBoolean(key, node.asBoolean());
} else {
// 对于其他未知类型,作为 null 处理
builder.putNull(key);
}
}
private static void buildMapFromNode(FlexBuffersBuilder builder, final String key, JsonNode objectNode) {
int mapStart = builder.startMap();
Iterator<Map.Entry<String, JsonNode>> fields = objectNode.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> field = fields.next();
buildFromNode(builder, field.getKey(), field.getValue());
}
builder.endMap(key, mapStart);
}
private static void buildVectorFromNode(FlexBuffersBuilder builder, String key, JsonNode arrayNode) {
int vecStart = builder.startVector();
for (JsonNode elementNode : arrayNode) {
// 递归构建数组中的每个元素
buildFromNode(builder, null, elementNode);
}
builder.endVector(key, vecStart, false, false);
}
/**
* 将 FlexBuffers 二进制转换为 Jackson JsonNode。
*
* @param buffer 包含 FlexBuffers 数据的 ByteBuffer。
* @return 转换后的 JsonNode。
*/
public static JsonNode convert(ByteBuffer buffer) {
FlexBuffers.Reference ref = FlexBuffers.getRoot(buffer);
return buildJsonNodeFromRef(ref);
}
/**
* 递归函数,根据 FlexBuffers 引用类型构建 JsonNode。
*
* @param ref 当前要处理的 FlexBuffers 引用。
* @return 构建好的 JsonNode。
*/
private static JsonNode buildJsonNodeFromRef(FlexBuffers.Reference ref) {
if (ref.isNull()) {
return JsonNodeFactory.instance.nullNode();
} else if (ref.isMap()) {
ObjectNode objectNode = JsonNodeFactory.instance.objectNode();
FlexBuffers.Map map = ref.asMap();
FlexBuffers.KeyVector keys = map.keys();
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i).toString();
// 递归构建 value
objectNode.set(key, buildJsonNodeFromRef(map.get(key)));
}
return objectNode;
} else if (ref.isVector()) {
ArrayNode arrayNode = JsonNodeFactory.instance.arrayNode();
FlexBuffers.Vector vector = ref.asVector();
for (int i = 0; i < vector.size(); i++) {
// 递归构建数组中的每个元素
arrayNode.add(buildJsonNodeFromRef(vector.get(i)));
}
return arrayNode;
} else if (ref.isString()) {
return JsonNodeFactory.instance.textNode(ref.asString());
} else if (ref.isInt()) {
final long value = ref.asLong();
if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) {
return JsonNodeFactory.instance.numberNode((int) value);
} else {
return JsonNodeFactory.instance.numberNode(value);
}
} else if (ref.isFloat()) {
return JsonNodeFactory.instance.numberNode(ref.asFloat());
} else if (ref.isBoolean()) {
return JsonNodeFactory.instance.booleanNode(ref.asBoolean());
}
return JsonNodeFactory.instance.nullNode();
}
}
jackson-dataformat-protobuf is for streaming (incremental) encoding/decoding of protobuf-encoded data so bit different.
This sounds like an idea for an optional "jackson-datatype-xxx" module that helps Jackson work with 3rd party value types. Maybe under https://github.com/FasterXML/jackson-dataformats-misc.