繁体   English   中英

如何反序列化深度嵌套的 JSON 而无需为每个级别单独的类

[英]How to deserialize deeply nested JSON without separate classes for each level

在 Java 中说我想反序列化一个 JSON 字符串,例如:

{ 
  "classb": {
    "c": "myc"
   }
}

所以我可以像这样创建模型类:

@Data
class Classa {
     Classb classb;
}

@Data
class Classb {
    String c;
}

并像这样打印反序列化的值:

System.out.println(new ObjectMapper().readValue(json, Classa.class).getClassb().getC()  );

所以我的问题是,当我们只对深度嵌套在类对象中的值感兴趣并且我们需要该值的 getter 时,我们是否必须为每个对象创建一个单独的模型类,或者有没有办法创建一个单个模型类,它包含这样的嵌套类,并且能够使用 getter 访问内部对象,如getC()

@Data
class Classa {
    class Classb {
        String c;
    }
}

您可以实施其中一种树遍历算法,例如深度优先搜索算法,并迭代节点树,直到找不到目标属性(或直到树被完全探索)。

基于 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;
}

这就是深度优先搜索可以递归实现的方式。 我们可以将返回类型更改为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM