提取嵌套JSON对象的架构

10

假设这是源json文件:

{    
    "name": "tom",
    "age": 12,
    "visits": {
        "2017-01-25": 3,
        "2016-07-26": 4,
        "2016-01-24": 1
    }
}

我想要得到:

[
  "age",
  "name",
  "visits.2017-01-25",
  "visits.2016-07-26",
  "visits.2016-01-24"
]

我可以使用以下命令提取键:jq '. | keys' file.json,但这将跳过嵌套的字段。如何包含那些字段?

3个回答

13
通过您的输入,调用如下:
jq 'leaf_paths | join(".")'

生成:

"name"
"age"
"visits.2017-01-25"
"visits.2016-07-26"
"visits.2016-01-24"

如果你想包含"visits",请使用paths。如果你希望结果是一个JSON数组,请用方括号括起来:[ ... ]
如果你的输入可能包含数组,除非你使用的是jq 1.6或更高版本,否则你需要显式地将整数索引转换为字符串;另外,由于leaf_paths现在已被弃用,你可能想使用它的def。结果如下:
jq 'paths(scalars) | map(tostring) | join(".")'

allpaths

要包括空路径,您可以使用以下定义的allpaths

def allpaths:
  def conditional_recurse(f):  def r: ., (select(.!=null) | f | r); r;
  path(conditional_recurse(.[]?)) | select(length > 0);

例子:

{"a": null, "b": false} | allpaths | join(".")

产生:

"a"
"b"

all_leaf_paths

假设 jq 版本为 1.5 或更高,我们可以通过遵循 builtin.jq 中使用的策略来获得 all_leaf_paths,即通过添加以下定义:

def allpaths(f):
  . as $in | allpaths | select(. as $p|$in|getpath($p)|f);

def isscalar:
  . == null or . == true or . == false or type == "number" or type == "string";

def all_leaf_paths: allpaths(isscalar);

例子:

{"a": null, "b": false, "object":{"x":0} } | all_leaf_paths | join(".")

产生:

"a"
"b"
"object.x"

我注意到,pathleaf_paths都忽略了值为nullfalse的字段。有什么办法可以包含它们吗? - nik
你的“allpaths”编辑看起来很有前途,但不幸的是,它似乎并没有按预期工作。它实际上会输出完整文件,包括属性值。 - nik
1
在理解了我只需要将您的自定义函数定义添加到一个~/.jq文件中后,一切都像魔法一样运行。很想再给您点赞! - nik
你不必将这些函数添加到~/.jq中--例如,您可以只是在命令行上使用-f选项指定的任何文件中包含它们。感谢虚拟的第二个赞同。 - peak

1

一段时间之前,我编写了一个结构模式推理引擎,它能够生成简单的结构模式,以反映正在考虑的JSON文档,例如对于这里给出的示例JSON,推断得到的模式为:

{
  "name": "string",
  "age": "number",
  "visits": {
    "2017-01-25": "number",
    "2016-07-26": "number",
    "2016-01-24": "number"
  }
}

这不完全是原始发布要求的格式,但对于大量对象的集合,它提供了有用的概览。

更重要的是,现在有一个互补的验证器,用于检查JSON文档集合是否与结构模式匹配。该验证器针对使用JESS(JSON扩展结构模式)编写的模式进行校验,这是由模式推断引擎生成的简单结构模式(SSS)的超集。

(想法是可以使用SSS作为起点添加更复杂的约束,包括递归约束、文档内引用完整性约束等。)

为参考起见,以下是使用"schema" module生成样本.json的SSS的方法:

jq 'include "schema"; schema' source.json > source.schema.json

并且要对source.json进行SSS或ESS验证:

JESS --schema  source.schema.json  source.json

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接