PBIDEA:用 uo_json 的 set/get 与路径语法操作 JSON
本帖最后由 pbai 于 2026-8-14 09:22 编辑PBIDEA:用 uo_json 的 set/get 与路径语法操作 JSON
做接口对接、配置文件、前端数据交换时,绕不开 JSON。PBIDEA 的 uo_json 把「建树、取值、改值」压成两个动作:set 和 get,再用一套 /items/0/text 的路径语法直接定位到数组里的任意一层。本文只讲清楚一件事:怎么用 set/get 配合路径语法,读写一棵带数组的 JSON,且中途自动建树、不会踩空。
一、核心结论先放这儿
[*]set(key, value):键不存在就自动创建,支持嵌套路径,先 set 父再 set 子也行,顺序随意。
[*]get(key, ref value):返回 boolean 表示是否取到,第二参是输出。取不到不会报错崩溃。
[*]路径语法:"a/b/c" 走对象,"a/0/b" 走数组第 0 个元素(0 基)。数组下标用数字即可。
[*]数字默认当 double 存,get 到 long/int 会自动转;要当字符串保留位数用 GetString。
二、最小可运行示例
下面这段代码不依赖任何业务,粘进按钮的 clicked 事件就能跑。它构造了一个带 items 数组的对象,再原样读回来:
uo_json js
js = create uo_json
// 1) 顶层字段:set 自动建树,先写谁都行
js.set("name", "小明")
js.set("age", 32) // 数字按 double 存
js.set("vip", true) // 布尔
// 2) 数组 + 路径语法:/items/0/text 表示 items 数组第 0 项的 text 字段
js.set("/items/0/text", "搜索")
js.set("/items/0/icon", "search.svg")
js.set("/items/1/text", "设置")
js.set("/items/1/icon", "gear.svg")
// 3) 取回——get 返回 boolean,取不到时变量保持原值,可给默认值
string ls_name, ls_first, ls_icon
if js.get("name", ls_name) then
// 成功
end if
js.get("/items/0/text", ls_first) // -> "搜索"
js.get("/items/1/icon", ls_icon) // -> "gear.svg"
// 4) 数字:get 到 long 自动转;想拿字符串用 GetString
long ll_age
js.get("age", ll_age) // -> 32
string ls_age
ls_age = js.GetString("age") // -> "32"
// 5) 数组长度 & 遍历
long ll_cnt, i
ll_cnt = js.ArrCount("items") // -> 2
string ls_t
for i = 0 to ll_cnt - 1
js.get("/items/" + string(i) + "/text", ls_t)
// 依次得到 "搜索"、"设置"
next
// 6) 导出
string ls_out
ls_out = js.ToString(true, false, false)// 美化输出,不转 unicode
destroy js
三、set 的几个易混点
set 的第二个参数类型
set 是重载的,第二参可以是 string / number(int,long,double,decimal...) / boolean / blob / uo_json / 数组。传 blob 时默认走 BASE64 编码(常量 SetBlob=1);想存原始字节序用 SetBytes=2 形式(带第三个参数 SetType)。日常配置基本只用 string/number/boolean。
路径里数组下标从 0 开始
这是最容易写错的地方。/items/1/text 是第 2 个元素。下标写错不会报错,只是 get 返回 false、取不到值——所以取数组前先用 ArrCount 确认长度,别硬取。
想直接塞一整个数组
可以用数组形式一次 set:
string ls_tags[] = {"pb", "ide", "json"}
js.set("tags", ls_tags) // tags 变成 ["pb","ide","json"]
long n
n = js.ArrCount("tags") // -> 3
四、从字符串 / 文件反向解析
接口返回的报文、本地配置文件,都是「先有字符串,再解析成对象」:
uo_json j2
j2 = create uo_json
// 解析内存字符串
if j2.Parse('{"code":0,"msg":"ok","data":["a","b"]}') then
long ll_code
j2.get("code", ll_code) // -> 0
end if
// 解析文件(中文路径注意编码)
if j2.ParseFile("menu_cn.json") then
// 后续同样用 get / 路径语法
end if
// 转成 UTF-8 BLOB,直接交给 uo_httpclient 发出去
blob b_body = j2.ToUTF8()
destroy j2
Parse 还有 Parse(str, removeEscape)、Parse(str, removeEscape, NumAsString) 等重载:网络报文常带转义,removeEscape=true 可顺手清掉;NumAsString=true 让所有数字以字符串形式保留(避免 1.0 变 1、丢精度)。
五、改值、删值、清空
js.Replace("name", "小红") // 替换已存在的节点
js.Remove("/items/0") // 删除数组第 0 项(后面的下标会自动前移)
js.Remove("vip") // 删除顶层字段
js.Clear() // 清空整棵对象
注意 Remove("/items/0") 删的是数组项,删掉后原第 1 项变成新的第 0 项——遍历时别用「先算长度再固定下标」的写法去删,会越界或漏删。
六、什么时候用便利方法
字段多、类型杂时,用 GetString / GetLong / GetDouble / GetLongLong 比 get(..., ref) 少写一行类型声明:
strings
long l
doubled
s = js.GetString("name", "") // 带默认值,取不到返回 ""
l = js.GetLong("age")
d = js.GetDouble("score")
GetKeys(ref keys[]) 能拿出全部顶层 key(含类型),做「通用遍历 / 不确定结构」时很实用。
七、小结
记住一条主线就够用:create uo_json → set(路径, 值) 建树 → get(路径, ref 变量) 取值(先判返回值)→ ToString/ToUTF8 导出。路径语法 /a/0/b 让「数组里套对象、对象里再套数组」的深层结构,也能一行定位。下一篇我们接着看怎么用它组装 HTTP 请求体发出去。
页:
[1]