从深度嵌套的JSON结构中提取值

在这里插入图片描述

  1. 问题背景
    在某些情况下,我们可能需要从深度嵌套的JSON结构中提取值。例如,给定以下JSON结构:
{
    "foo_code": 404,
    "foo_rbody": {
        "query": {
            "info": {
                "acme_no": "444444",
                "road_runner": "123"
            },
            "error": "no_lunch",
            "message": "runner problem."
        }
    },
    "acme_no": "444444",
    "road_runner": "123",
    "xyzzy_code": 200,
    "xyzzy_rbody": {
        "api": {
            "items": [
                {
                    "desc": "OK",
                    "id": 198,
                    "acme_no": "789",
                    "road_runner": "123",
                    "params": {
                        "bicycle": "2wheel",
                        "willie": "hungry",
                        "height": "1",
                        "coyote_id": "1511111"
                    },
                    "activity": "TRAP",
                    "state": "active",
                    "status": 200,
                    "type": "chase"
                }
            ]
        }
    }
}

我们可能需要提取以下值:

  • foo_rbody.query.info.acme_no
  • foo_rbody.query.info.road_runner
  • xyzzy_rbody.api.items[0].params.bicycle
  1. 解决方案
    有多种方法可以从深度嵌套的JSON结构中提取值。以下是一些最常用的方法:
  • 使用get_path()函数
import re

def get_path(dct, path):
    for i, p in re.findall(r'(\d+)|(\w+)', path):
        dct = dct[p or int(i)]
    return dct

value = get_path(data, "xyzzy_rbody.api.items[0].params.bicycle")
  • 使用递归函数
def get_value(dct, path):
    if isinstance(dct, dict):
        for key, value in dct.items():
            if key == path:
                return value
            else:
                result = get_value(value, path)
                if result is not None:
                    return result
    elif isinstance(dct, list):
        for i, item in enumerate(dct):
            if i == path:
                return item
            else:
                result = get_value(item, path)
                if result is not None:
                    return result
    return None

value = get_value(data, "xyzzy_rbody.api.items[0].params.bicycle")
  • 使用Pynq库
import pynq

data = {
    "foo_code": 404,
    "foo_rbody": {
        "query": {
            "info": {
                "acme_no": "444444",
                "road_runner": "123"
            },
            "error": "no_lunch",
            "message": "runner problem."
        }
    },
    "acme_no": "444444",
    "road_runner": "123",
    "xyzzy_code": 200,
    "xyzzy_rbody": {
        "api": {
            "items": [
                {
                    "desc": "OK",
                    "id": 198,
                    "acme_no": "789",
                    "road_runner": "123",
                    "params": {
                        "bicycle": "2wheel",
                        "willie": "hungry",
                        "height": "1",
                        "coyote_id": "1511111"
                    },
                    "activity": "TRAP",
                    "state": "active",
                    "status": 200,
                    "type": "chase"
                }
            ]
        }
    }
}

query = pynq.select("xyzzy_rbody.api.items[0].params.bicycle")
value = query(data)
<think>好的,用户想了解如何使用jsmn来获取嵌套JSON值。我需要先回忆一下jsmn的基本用法,因为它是C语言中一个轻量级的JSON解析器。首先,jsmn通过分词的方式工作,将JSON字符串分解成一个个token,每个token代表一个元素,比如对象、数组、字符串、基本类型等。 用户的问题是关于嵌套结构的处理,所以需要解释如何遍历这些token来访问嵌套的数据。我应该先介绍jsmn的基本解析流程,然后详细说明如何处理嵌套的对象或数组。 可能需要注意几点:jsmn的token结构包含类型、起始位置和长度,但没有直接的层级信息,所以必须手动跟踪层级和结构。例如,当遇到一个对象时,内部的键值对会作为连续的token,而嵌套的对象或数组会增加层级深度,需要用栈或计数器来管理。 接下来,我应该举例说明。比如,一个包含嵌套对象的JSON,解析后如何定位到内部的某个字段。可能需要遍历父对象的token,找到对应的键,然后跳到其值的位置,如果是嵌套结构,继续递归或迭代处理。 还需要醒用户注意错误处理,比如键不存在或者结构不符合预期的情况,因为jsmn本身不供查找功能,需要用户自己实现这些逻辑。 可能用户在使用过程中会遇到的问题包括:错误计算token的位置导致字符串截取错误,或者层级管理不当导致访问错误的嵌套层级。因此,在步骤说明中需要强调仔细处理每个token的关系和位置。 最后,总结一下步骤:解析生成token数组,遍历token,使用递归或栈来处理嵌套结构,正确跳转到目标层级的token,然后取对应的值。这样用户应该能理解如何通过jsmn获取嵌套JSON值了。</think>jsmn是一个轻量级JSON解析器,适用于嵌入式系统等资源受限场景。处理嵌套JSON值的核心思路是通过递归遍历token层级结构。以下是分步说明: 1. **解析阶段** ```c jsmn_parser parser; jsmntok_t tokens[128]; // 根据JSON复杂度预分配 jsmn_init(&parser); int count = jsmn_parse(&parser, json_str, strlen(json_str), tokens, 128); ``` 2. **token结构分析** 每个token包含: - `type`:类型(对象、数组、字符串等) - `start/end`:在原始字符串中的位置 - `size`:子元素数量(对象包含键值对数,数组包含元素数) 3. **递归遍历示例** 假设解析以下JSON: $${ "user": { "name": "Alice", "age": 30, "address": { "city": "Beijing", "zip": "100000" } } }$$ 4. **定位嵌套值的关键步骤 ```c // 假设已找到"user"键的token索引为user_idx int addr_idx = find_key(tokens, user_idx+1, "address"); // 跳转到address对象内部 int city_idx = find_key(tokens, addr_idx+1, "city"); char* city = copy_token_str(json_str, &tokens[city_idx+1]); ``` 5. **关键工具函数示例 ```c int find_key(jsmntok_t* tokens, int start, const char* key) { for (int i = start; i < num_tokens; i++) { if (tokens[i].type == JSMN_STRING && strneq(json_str + tokens[i].start, key, tokens[i].end - tokens[i].start)) { return i; // 返回键的索引 } } return -1; } ``` **注意事项** 1. 对象内部结构:键值对按`[键][值][键][值]...`顺序排列 2. 嵌套层级管理:建议使用栈结构记录当前层级 3. 数组处理:通过`size`字段确定数组长度,元素按顺序排列 4. 错误处理:必须检查每个步骤的返回值,防止越界访问 该方法需要手动维护解析状态,对于复杂JSON建议结合路径解析算法(如JSONPath)来实现更灵活的查询。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值