递归方法读取任意深度的 JSON 对象的键值

如何优雅解析多层嵌套的复杂JSON数据 OGNL全称 “对象图导航语言”,我们可以使用其提供的表达式语言获取JAVA对象树中的任意属性或调用其方法。不仅如此,它还能自动实现必要的类型转换,废话不多说,我们来看看如何使用吧。 阅读详情

有以下json字符串

{
    "name":"John",
    "age":30,
    "address":{
        "city":"New York",
        "state":"NY",
        "zip":"10001",
        "coordinates":{
            "latitude":40.712776,
            "longitude":-74.005974,
            "accuracy":5,
            "details":{
                "description":"Exact location of the building"
            }
        },
        "details":{
            "street":"123 Main St",
            "apt":"4B",
            "building":{
                "name":"Central Park Tower",
                "floors":98,
                "amenities":{
                    "gym":true,
                    "pool":true,
                    "parking":{
                        "garage":true,
                        "valet":true
                    }
                }
            }
        }
    }
}

读取valet层级中的值

1、maven中导入依赖,导入了两种json字符串转JsonObject的依赖

<dependencies>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20210307</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.15</version>
        </dependency>


    </dependencies>

2、实现递归读取json中某一层级的key值


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
//import org.json.JSONObject;

public class ReadJson {

    public static void main(String[] args) {
        String jsonString = "{\"name\":\"John\",\"age\":30,\"address\":{\"city\":\"New York\",\"state\":\"NY\",\"zip\":\"10001\",\"coordinates\":{\"latitude\":40.712776,\"longitude\":-74.005974,\"accuracy\":5,\"details\":{\"description\":\"Exact location of the building\"}},\"details\":{\"street\":\"123 Main St\",\"apt\":\"4B\",\"building\":{\"name\":\"Central Park Tower\",\"floors\":98,\"amenities\":{\"gym\":true,\"pool\":true,\"parking\":{\"garage\":true,\"valet\":true}}}}}}";
        //JSONObject json = new JSONObject(jsonString);
         JSONObject json = JSON.parseObject(jsonString);
        //valet在第五层级
        String valetParking = getValueByKey(json, "valet");
        System.out.println(valetParking);
    }

    public static String getValueByKey(JSONObject json, String key) {
        String result = null;
        for (String k : json.keySet()) {
            Object value = json.get(k);
            if (value instanceof JSONObject) { //遇到jsonobject继续递归
                result = getValueByKey((JSONObject) value, key);
                if (result != null) {
                    break;
                }
            } else if (k.equals(key)) { //遇到某一层级的叶子节点如果和key相等于,找到答案跳出循环返回一个result,然后再回到递归getValueByKey返回一个结果,判断不为空跳出本次递归的循环,return返回结果,再回到之前的递归返回的结果还是之前的直接不为空跳出本次递归的循环,返回return,接着再回到之前的递归....
                result = value.toString();
                break;
            }
        }
        return result;
    }

}

运行过程:遇到jsonobject继续递归;遇到某一层级的叶子节点如果和key相等于,找到答案跳出循环执行return result,然后再回到递归getValueByKey返回刚才的return结果,判断不为空跳出本次递归的循环,return返回结果,再回到之前的递归返回的结果还是之前的直接不为空跳出本次递归的循环,返回return结果,接着再回到之前的递归....最终走完递归

缺点:如果寻找的key在多个层级存在,只能返回最近一个层级的key

优点:只需要传我想要的key即可

针对多个层级存在相同key的问题,可以使用下面的代码来实现

import org.json.*;

public class ReadJsonV2 {
    public static void main(String[] args) {
        // 要解析的JSON字符串
        String jsonString = "{\"name\":\"John\",\"age\":30,\"address\":{\"city\":\"New York\",\"state\":\"NY\",\"zip\":\"10001\",\"coordinates\":{\"latitude\":40.712776,\"longitude\":-74.005974,\"accuracy\":5,\"details\":{\"description\":\"Exact location of the building\"}},\"details\":{\"street\":\"123 Main St\",\"apt\":\"4B\",\"building\":{\"latitude\":\"Central Park Tower\",\"floors\":98,\"amenities\":{\"gym\":true,\"pool\":true,\"parking\":{\"garage\":true,\"valet\":true}}}}}}";

        // 解析JSON字符串
        JSONObject jsonObject = new JSONObject(jsonString);

        // 获取某个层级的键
        //String keyString = "address.coordinates.latitude";
        String keyString = "address.details.building.latitude";

        String[] keys = keyString.split("\\.");
        String make = getJsonValue(jsonObject, keys);
        System.out.println(make); // 输出 "Ford"
    }

    private static String getJsonValue(JSONObject jsonObject, String[] keys) {
        JSONObject currentObject = jsonObject;
        for (String key : keys) {
            if (currentObject.has(key)) {
                Object obj = currentObject.get(key);
                if (obj instanceof JSONObject) {
                    currentObject = (JSONObject) obj;
                } else {
                    return obj.toString();
                }
            } else {
                return null;
            }
        }
        return null;
    }
}

在这个实现中,我们将传入的键名字符串"address.details.building.latitude"拆分成一个字符串数组{"address", "details","building","latitude"}。然后,我们将该数组传递给getJsonValue方法,该方法使用该数组来遍历JSON对象。如果存在该键名,则将其转换为JSON对象类型并将其赋值给currentObject。如果该键名不存在,返回null。如果该键对应的对象不是JSON对象类型,则将其转换为字符串并返回。

通过这种方式,我们可以轻松地使用点号分隔的字符串来查找JSON对象中的任何层级的键值对。

JSON字符串深度递归解析技术详解 递归的本质是“自己调用自己”,特别适合处理具有自相似结构的数据。而 JSON 正好就是一棵典型的树形结构:"users": [每一层的对象或数组,其子节点又可能是新的对象或数组——这种无限嵌套的可能性,天然契合递归模型。递归三要素:1.分治思想:把大问题拆成小问题2.递归入口:遇到复合结构就再次进入3.终止条件:碰到基本类型就返回来看一个极简版的手动解析框架:// 终止条件:基础类型直接返回// 数组:递归处理每个元素。 阅读详情

相关推荐

Python深度遍历嵌套字典:递归查找键值的实战方法

Python 开发中,接口返回的 JSON 与配置数据常以多层嵌套字典形式存在,取值时手工索引极易因层级缺失或列表夹层而报错。递归通过终止条件、规模缩小与自我调用三个要素,将任意深度的结构遍历简化为统一逻辑:遇到字典遍历键值,遇到列表逐个深入,实现深度遍历查找字典键对应的值。该方案能提升数据解析的健壮性,广泛应用于配置提取、接口字段校验、动态键名匹配等工程场景。掌握递归遍历嵌套字典的方法,可让复杂 JSON 数据的取值从逐层手写索引简化为一行调用,显著提高开发效率。

weixin_29913663的博客 212

多层JSON字符串取值

【代码】多层JSON字符串取值。

dcz1996的博客 952

JavaScript中深度比较JSON数据的技巧与实践

在JavaScript中,经常需要对数据进行比较操作,尤其当涉及到JSON数据结构时,情况就变得复杂。JSON数据通常是由嵌套的对象和数组组成的复杂结构,简单地使用等号==或全等号===可能无法准确判断两个JSON对象是否在逻辑上相等。当我们在应用程序中进行数据同步、状态更新或前后端数据校验时,正确地比较两个JSON对象是否相等就显得尤为重要。在JavaScript中,严格相等运算符===是一个用于比较两个值是否完全相等的运算符。它不仅比较值的相等性,同时也会比较值的类型。

weixin_42613018的博客 996

递归获取复杂对象的所有键key

突发奇想想练练递归(很能锻炼逻辑思维),虽然好像实际应用不会要求取对象所有的key 代码: // 目标对象 const TARGET = { a: { b: { c: 1 }, e: 4, f: 5, g: 6 }, wo:{ xixi:233 } } // 获得的key数组 var arr = [] // 通过递归获取对象所有key function qu

muyumuyu98的博客 806

基于递归实现的JSON拆分工具类设计与实战

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用键值对(Key-Value Pair)和嵌套结构来表示数据。其基本结构包括:对象(Object):使用花括号{}包裹,键值对之间用冒号分隔,多个键值对之间用逗号分隔。数组(Array):使用方括号[]包裹,元素之间用逗号分隔。基本数据类型:包括字符串(String)、数值(Number)、布尔值(Boolean)、null 和对象或数组的嵌套。

weixin_35755823的博客 753

WPS接入DeepSeek,实现AI辅助功能

总的来说,借助 WPS 中宏功能与 DeepSeek 大模型的结合,文档处理、内容创作和数据分析等任务都能更加智能化、自动化。这不仅大幅提升了工作效率,也为办公场景带来了全新的智能化办公体验。

运维老生常谈 3801

Javascript 根据key值取出对应的Value值

根据key值取出对应的Value值,返回所有的value值的数组 getValueByKey(arrayList) { const arrayPickerData = []; arrayList.forEach((Item) => { const key = Object.keys(Item); arrayPickerData.push(Item[ke...

Donkey的博客 8752

gesp c++ 八级知识点

gesp c++ 八级知识点

MMD.然大大 2233

JAVA调用shell

  StringBuilder result = new StringBuilder();    InputStream in = proc.getInputStream();  BufferedReader buf = new BufferedReader(new InputStreamReader(in, "gbk"));  String line = null;  while ((line ...

changhui_liang的博客 344

D类功放几种常见“爆破音”问题根源与改善措施

在数字D类功放刚上电或功放播放状态切换时,人耳偶尔会听到“嘣”的声音,我们把这个爆破的Pop Noise。数字功放Pop Noise 出现的原因有很多,本文主要分析Pop Noise 出现原因,并提供相应解决方法。

qq_26815321的博客 3589

手把手教你用Python模拟侧信道攻击:从电磁辐射到数据窃取(附防御代码)

本文详细介绍了如何使用Python模拟侧信道攻击,从电磁辐射信号采集到数据窃取的全过程,并提供了实用的防御代码。通过实战案例,帮助安全研究员和开发者理解侧信道攻击原理,掌握信号处理与图像重建技术,同时学习有效的噪声干扰和电磁屏蔽防御措施。

weixin_28716443的博客 161

Flutter 三方库 sort_json 的鸿蒙化适配指南 - 实现 JSON 键值的自动化递归排序、支持规范化输出与项目配置文件清理

在进行 Flutter for OpenHarmony 的工程化开发时,保持项目配置文件(如.json5或各种国际化语言文件)的条理性是至关重要的。特别是在多人协作或版本控制(Git)中,无序的 JSON 键值会导致严重的冲突。sort_json是一个专注于将 JSON 字符串或文件重新排版并按字母顺序排序的库。本文将探讨如何利用该工具优化鸿蒙项目的配置管理。sort_json通过将输入的 JSON 文本解析为 Dart 的Map。

好代码自己会说话,烂代码才需要注释来圆谎 3489

云模型在综合评价过程中的应用

目录 1 云模型标尺(标准云模型)的构建方法 1.1 通过正态云的“3En 规则”来表示评价论域 1.2 通过论域的边界值隶属度相等来表示评价论域 1.3 通过黄金分割法来表示评价论域 2 确定评价结果的过程 2.1 基本云发生器 2.2 X条件云发生器 2.3 两种方法的区别 综合评价问题一般分为以下六个步骤 1、明确评价目的; 2、确定被评价对象; 3、建立评价指标体系(包括收集评价指标的原始值、评价指标的若干预处理等); 4、确立与各项评价指标相对应的权重系数; 5、选..

weixin_62223576的博客 1万+

递归遍历JSON

function filterStrByJSON(json) { //Test Data var _rsObj = [{ "a": 123, "b": [{ "c1": "rdpdt-001" }, { "c2": "rdpdt-001" } ], "d": "rdpdt-001" }, { "a": 123, "...

天空源的博客 1026

学Simulink——基于Simulink的AUTOSAR架构下电机控制软件组件建模

本文详细介绍了在Simulink中基于AUTOSAR架构开发电机控制软件组件(SWC)的全流程。主要内容包括:首先阐述了AUTOSAR架构对汽车电子系统开发的价值,包括提高软件复用率、降低集成成本和改善验证环境。然后重点讲解了在Simulink中构建电机控制SWC的具体步骤:从创建AUTOSAR组件模型、定义数据端口和服务端口,到搭建FOC控制算法、配置运行实体,最后生成AUTOSAR描述文件和验证RTE接口。文章还提供了与基础软件(BSW)的集成方案、工程实践要点和常见问题解决方案,并以大众MEB平台等实

amy_mhd的博客 66

【LOGO动态替换】记录一次关于LOGO动态替换引发的uboot代码分析及其实现

文章目录1.前言2.实现2.1 新增logo分区2.2 制作logo分区镜像2.2.1 查看logo.bmp和logo_kernel.bmp的文件大小。2.2.2 按规则将bmp写入logo.img3.分析3.1 uboot的启动分析3.2 uboot bmp load 显示部分3.2.1 rockchip_show_logo3.2.2 load_bmp_logo3.2.3 load_bmp_logo3.3 uboot bmp read部分3.3.1 read_logo_bmps3.3.1 read_bmp

wang 恒 的博客 1211

通用JSON遍历方案:递归处理任意复杂JSONObject与JSONArray

JSON作为键值对与有序集合的嵌套组合,其遍历本质是递归处理对象与数组两种容器。通过先判null、再判容器、最后判叶子的类型分流策略,结合路径追踪与延迟修改机制,可构建一套稳定、可复用的通用遍历骨架。该方案在接口数据清洗、字段脱敏、结构扁平化及统计聚合等场景中具有广泛工程价值,能有效规避空指针、并发修改异常与栈溢出等常见陷阱。掌握JSONObject与JSONArray的递归遍历模型,即可在不同语言与库之间快速迁移,将遍历逻辑与业务处理解耦,提升代码健壮性与可维护性。

weixin_29313817的博客 180

2023华为od机试【最小循环子数组】C++

2023华为od机试【最小循环子数组】C++ 给定一个由若干整数组成的数组nums,请检查数组是否是由某个子数组重复循环拼接而成,请输出这个最小的子数组。

MISAYAONE的博客 2185

JS(递归)对比两个对象的值是否相等,并且可以排除不想对比的键值对。

JS对比两个对象的值是否相等,并且可以排除不想对比的键值对。 ##在项目中,我们需要判断用户是否对表单内的内容做过修改,假设有两种场景,一是用户新增的时候,二是用户修改的时候。 ##无论是用户修改还是新增,我们都可以拿到表单内的初始数据,使用vue项目来说, 我们可以使用 this.$options.data().XXX//来拿到初始数据 this.XXX//拿到修改后的数据,这时候就需要对这两组数据进行对比 一、不排除里面的键,直接对比 JSON.stringify(XXX)==JSON.s

L_TZzzz的博客 1599

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

C语言处理复杂JSON数据的秘诀(递归解析实战详解)

掌握C语言嵌套JSON的递归解析实现,轻松应对复杂数据处理。适用于物联网、配置解析等场景,通过递归遍历实现高效访问深层数据,代码简洁且内存安全。值得收藏的实战指南,点击了解详情。

VarPerch的博客 1049

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

nlohmann/json update() 详解:C++ 中 JSON 对象的覆盖更新与递归合并

`update()` 是 nlohmann::basic_json 提供的对象级合并接口,对应 Python `dict.update` 的语义:把一个 JSON 对象(或迭代器区间)中的所有键值对写入当前对象,可选择性地对嵌套对象做递归合并。本文基于仓库 API 文档 [update.md](https://link.gitcode.com/i/d7b43e6d975ec8bfc2da8b2d0

gitblog_00066的博客 496

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

JSON对象遍历

JSON对象的遍历: 1.对key-value对类型的遍历; 2.对数组元素的遍历 3.对嵌套的json结构遍历

ThinkingLink的专栏 2万+

JAVA JSON转XML

主要jar包用到dom4j和gson。大致思路就是写一个方法遍历json的每一个key和value,碰到有深度的key重复调用本方法(也就是递归啦) public class JsonToXml { private static final String STR_JSON = "{\"name\":\"yato233\",\"address\":{\"city\":\"beijing\",\"street\":\" longyu Road \",\"postcode\":100000},\"bl.

baidu_37366055的博客 4514

Go基于反射实现任意结构json值的替换

最近面临一个应用场景,需要对一个倒手转发的json进行数据替换,查阅了众多的库,大部分都不支持这个功能,从历史项目里捞出了jsonpath这个库,但只能根据jsonpath的schema进行Get操作,无法inplace回写,后来又找到sjson,这是个根据jsonpath回写的库,没有用反射,自己实现的parser,但是在数组、对象混合嵌套的结构中,没办法正确写入,因为在使用gjson提取值之后,已经丢失了原始路径信息。在经过一番折腾之后,还是决定自己写一个替换器,虽然反射效率会比较低,但是好歹能实现,也

一只Coding猪 1745

FastAPI `jsonable_encoder` 深度解析:把任意 Python 对象转为 JSON 兼容数据

本文围绕 FastAPI 官方 API 参考文档 [encoders.md](https://link.gitcode.com/i/f182669682b04b31dacb260e1acc24f6)(即 `fastapi.encoders.jsonable_encoder` 的参考页)展开,完整讲解该函数的用途、全部参数、内置类型编码规则与底层实现流程。读完本文后,你将能够:在业务代码中把 Pyd

gitblog_00239的博客 283

C语言实现JSON解析器核心技术(递归解析深度剖析)

掌握C语言嵌套JSON的递归解析实现,深入剖析JSON解析器核心机制。适用于嵌入式系统与高性能场景,采用递归下降法精准处理多层嵌套结构,具备内存占用低、解析效率高的优势,是构建轻量级解析器的关键技术,值得收藏。

QuickSolve的博客 1069
上一篇: 什么是圈复杂度
下一篇: java中常见的json库以及对应的用法
魑魅魍魉114
博客等级 码龄10年 165粉丝 240原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值