You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用libyang创建YANG带键列表节点并写入操作数据存储

问题描述

基于sysrepo示例YANG模型新增了WiFi扫描结构,其中scan容器下的bss列表以bssid为键,需要写入操作数据存储。使用libyang的lyd_new_path创建带键列表节点时,仅能生成bssid字段,其他字段无法添加;若不指定[bssid='...']谓词,会报错:

libyang[0]: 路径"/examples:scan/bss"中的列表"bss"缺少谓词。(路径: 模式位置"/examples:scan/bss"。)

YANG代码片段

container scan {
    config false;
    list bss {
        key "bssid";
        leaf ssid { type string; }
        leaf bssid { type string; }
        leaf channel { type uint32; }
        leaf frequency { type uint32; }
        leaf chan_width { type int16; }
        leaf signal_strength { type int16; }
    }
}

尝试的C代码

const char *s = "{\"bss\":[{\"bssid\":\"00:40:68:aa:bb:cc\",\"chan_width\":0,\"channel\":48,\"frequency\":5240,\"signal_strength\":0,\"ssid\":\"Hello World\"}]}";

err = lyd_new_path(NULL, ly_ctx, "/examples:scan/bss[bssid='00:40:68:aa:bb:cc']", s, 0, parent);
printf("err=%d msg=%s parent=%p\n", err, ly_errmsg(ly_ctx), (void*)*parent);

// 无数据测试是否成功(成功)
err = lyd_new_path(*parent, ly_ctx, "/examples:scan/bss[bssid='00:40:68:11:22:33']", NULL, 0, NULL);
printf("err=%d msg=%s parent=%p\n", err, ly_errmsg(ly_ctx), (void*)*parent);

lyd_print_path("/tmp/test.json", *parent, LYD_JSON, 0);

解决方案

1. 匹配路径与数据层级

lyd_new_path的第四个参数(数据字符串)必须和路径指向的节点层级完全匹配。你当前路径指向的是单个bss列表项,但传入的JSON是包含bss数组的顶层结构,libyang无法识别这种不匹配的层级,因此只会解析出路径中指定的bssid字段。

2. 单个列表项的正确创建方式

针对单个bss列表项,传入的JSON应仅包含该列表项的字段键值对,无需外层的bss数组:

// 仅保留单个bss项的字段数据
const char *s = "{\"chan_width\":0,\"channel\":48,\"frequency\":5240,\"signal_strength\":0,\"ssid\":\"Hello World\"}";

// 路径指定具体bssid的列表项,传入对应字段数据
err = lyd_new_path(NULL, ly_ctx, "/examples:scan/bss[bssid='00:40:68:aa:bb:cc']", s, 0, parent);

3. 批量创建多个列表项

如果需要一次性添加多个bss项,可以直接传入包含完整scan容器结构的JSON,路径指向scan容器即可:

// 完整的scan容器JSON,包含多个bss项
const char *s = "{\"bss\":[{\"bssid\":\"00:40:68:aa:bb:cc\",\"chan_width\":0,\"channel\":48,\"frequency\":5240,\"signal_strength\":0,\"ssid\":\"Hello World\"}, {\"bssid\":\"00:40:68:11:22:33\",\"chan_width\":2,\"channel\":1,\"frequency\":2412,\"signal_strength\":-50,\"ssid\":\"Test AP\"}]}";

// 路径指向scan容器,直接导入完整结构
err = lyd_new_path(NULL, ly_ctx, "/examples:scan", s, 0, parent);

4. 谓词的必填性说明

bss是带键的列表,libyang要求必须通过谓词([bssid='xxx'])指定唯一的列表项,否则无法定位要操作的具体节点,因此不指定谓词必然报错,这是符合YANG模型规范的正常行为。

验证结果

修改后调用lyd_print_path生成的JSON会包含所有指定字段,示例输出:

{
  "examples:scan": {
    "bss": [
      {
        "bssid": "00:40:68:aa:bb:cc",
        "ssid": "Hello World",
        "channel": 48,
        "frequency": 5240,
        "chan_width": 0,
        "signal_strength": 0
      },
      {
        "bssid": "00:40:68:11:22:33",
        "chan_width": 2,
        "channel": 1,
        "frequency": 2412,
        "signal_strength": -50,
        "ssid": "Test AP"
      }
    ]
  }
}

内容的提问来源于stack exchange,提问作者David Poole

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 22:47:36