[英]How to deserialize deeply nested JSON without separate classes for each level
Say in Java I want to deserialize a JSON string such as:在 Java 中说我想反序列化一个 JSON 字符串,例如:
{
"classb": {
"c": "myc"
}
}
So I can create model classes like so:所以我可以像这样创建模型类:
@Data
class Classa {
Classb classb;
}
@Data
class Classb {
String c;
}
And print the deserialized value like so:并像这样打印反序列化的值:
System.out.println(new ObjectMapper().readValue(json, Classa.class).getClassb().getC() );
So my question is, when we are only interested in a value that is deeply nested in class objects and we need a getter for that value, do we have to create a separate model class for each object, or is there a way to create a single model class which contains the nested classes like this, and be able to access the inner objects with a getter, like getC()
所以我的问题是,当我们只对深度嵌套在类对象中的值感兴趣并且我们需要该值的 getter 时,我们是否必须为每个对象创建一个单独的模型类,或者有没有办法创建一个单个模型类,它包含这样的嵌套类,并且能够使用 getter 访问内部对象,如getC()
@Data
class Classa {
class Classb {
String c;
}
}
You can implement one of the tree-traversal algorithms, for instance Depth first search algorithm , and iterate over the tree of Nodes until the target property wasn't found (or until the tree is fully explored).您可以实施其中一种树遍历算法,例如深度优先搜索算法,并迭代节点树,直到找不到目标属性(或直到树被完全探索)。
That how iterative implementation of the Depth first search based on functionality of the Jackson's JsonNode
might look like:基于 Jackson 的JsonNode
功能的深度优先搜索的迭代实现可能如下所示:
public static <T> T search(String json, String target, Class<T> tClass) throws JsonProcessingException {
JsonNode node = new ObjectMapper().readTree(json);
T result = null;
Deque<JsonNode> stack = new ArrayDeque<>();
stack.push(node);
while (!stack.isEmpty()) {
JsonNode current = stack.pop();
if (current.isContainerNode()) {
for (Iterator<Map.Entry<String, JsonNode>> it = current.fields(); it.hasNext(); ) {
Map.Entry<String, JsonNode> next = it.next();
if (next.getKey().equals(target)) {
result = tClass.cast(next.getValue());
}
stack.push(next.getValue());
}
}
}
return result;
}
And that's how Depth first search can implemented recursively.这就是深度优先搜索可以递归实现的方式。 Instead of returning null
as a default value we can change the return type to Optional
(it can be done in the previous version as well).我们可以将返回类型更改为Optional
,而不是返回null
作为默认值(在以前的版本中也可以这样做)。
public static <T> Optional<T> search(String json, String target, Class<T> tClass) throws JsonProcessingException {
JsonNode node = new ObjectMapper().readTree(json);
Object result = search(node, target);
return result != null ? Optional.of(tClass.cast(result)) : Optional.empty();
}
public static Object search(JsonNode node, String target) {
if (!node.isContainerNode()) return null;
Object result = null;
for (Iterator<Map.Entry<String, JsonNode>> it = node.fields(); it.hasNext() && result == null; ) {
Map.Entry<String, JsonNode> next = it.next();
if (next.getKey().equals(target)) {
return next.getValue();
}
result = search(next.getValue(),target);
}
return result;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.