如何将 JSON 字典向量转换为 DolphinDB 内存表?
可以先创建一个列类型明确的内存表,再逐个读取 respData 中的字典,按列顺序转换字段,并通过 tableInsert 写入。这样既能展开字典,也能将 r_z_top50cap 中的 null 保存为 DOUBLE 类型空值。
为什么原来的方法失败?
fromStdJson 会将 JSON 数组转换为向量,将对象转换为字典。JSON number 转换为 DOUBLE,null 转换为 NULL。字符串会先尝试转换为时序类型,转换失败则保留为字符串,因此 da 的实际类型要以解析结果为准。fromStdJson 文档
几种尝试遇到的问题各不相同:
table(respData)将字典向量作为一列,没有按键展开。each(transpose, respData)逐个转换字典时遇到了未指定目标类型的空值。报错中的[VOID]表明该值无法直接作为表列的类型。respData.values()的调用对象是外层向量,不能直接收集内部各字典的字段。可以先取出字典,再通过row["字段名"]读取值。
transpose 支持将字典转换为表,但不会为这个报错中的 VOID 值确定 DOUBLE 列类型。transpose 文档
按固定列结构转换并写入
以下代码接在获取 resp 之后执行,前提是题目中的七个字段都存在、日期有效,且数值字段为数字或 null:
respData = fromStdJson(resp["text"])
colNames = `code`da`r_z_s`r_z_all`r_z_gics`r_z_sub_gics`r_z_top50cap
colTypes = [STRING, DATE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]
t = table(100:0, colNames, colTypes)
for (row in respData) {
daValue = row["da"]
if (typestr(daValue) == "STRING") {
daValue = temporalParse(daValue, "yyyy-MM-dd")
}
tableInsert(t, (
string(row["code"]),
date(daValue),
double(row["r_z_s"]),
double(row["r_z_all"]),
double(row["r_z_gics"]),
double(row["r_z_sub_gics"]),
double(row["r_z_top50cap"])
))
}
select * from t
table(100:0, ...) 创建一个初始容量为 100、当前行数为 0 的内存表。每次 tableInsert 传入一个包含七个字段的 tuple,元素的位置和类型与目标表的七列对应。tableInsert 支持这种写法,并返回本次插入的行数。tableInsert 文档
代码中的类型处理包括:
- 数值字段统一调用
double(...)。NULL 转换后会得到 DOUBLE 类型空值,保留缺失值的含义。官方示例中也有double(NULL)的用法。eqPercent 文档 - 如果
da仍为 STRING,就按yyyy-MM-dd解析;如果已经是时序类型,则通过date(...)转为 DATE。temporalParse的格式分隔符需要与输入一致。temporalParse 文档
如何检查转换结果?
可以查看表结构和关键字段:
schema(t).colDefs
select code, da, r_z_top50cap from t
题目提供的 JSON 预期转换为 3 行、7 列:code 为 STRING,da 为 DATE,其余五列为 DOUBLE。r_z_top50cap 的第一行和第三行为 DOUBLE 空值,第二行为 2.1884785540779355。
使用时要注意什么?
列顺序由 colNames 和写入的 tuple 共同确定。读取字段时按键名访问,所以不依赖字典键的枚举顺序。
不要仅根据第一行的值推断列类型。示例中第一行的 r_z_top50cap 是 null,第二行却有数值,应根据字段定义将整列设为 DOUBLE。
如果接口可能缺少字段、返回嵌套对象或改变日期格式,需要在写入前补充校验。日期解析后也应检查结果是否为空,避免把格式错误当作正常缺失值。对于较大的响应,可以按列收集为有类型的向量后批量写入;逐行写法适合先解决示例中的转换和空值问题。
备注:内容仅供参考。
