提取大部分JSON文件的有效部分



我使用jq来解析这个文件:

Successes: 0
Failures: 1
{
name: '',
success: false,
error: '',
data: {
video: ''
}
}

显然运行jq < foo.json得到:

parse error: Invalid numeric literal at line 1, column 10

因为无法解析

Successes: 0
Failures: 1

是否有方法使用Bash或jq本身来提取剩余部分,这是有效的JSON?

{
name: '',
success: false,
error: '',
data: {
video: ''
}
}

如果您在开头添加一行'[',在末尾添加另一行']',则:

hjson -j  input.txt

收益率:

[
"Successes: 0",
"Failures: 1",
{
"name": "",
"success": false,
"error": "",
"data": {
"video": ""
}
}
]

由于这是有效的JSON,您可以将其管道到jq以提取您想要的任何部分。

一个有趣的无损可能性是识别键值对:

jq 'map(if type == "string" and index(":") 
then [splits(": *")]
| {(.[0]): .[1] | (tonumber? // .)}
else . end)'

对于您的示例,这将产生:

[
{
"Successes": 0
},
{
"Failures": 1
},
{
"name": "",
"success": false,
"error": "",
"data": {
"video": ""
}
}
]

警告

上面的假设是,如果顶级项是一个有多个冒号的字符串,那么放弃第二个冒号之后的字符串内容是可以接受的。

添加另一种猜测,虽然这不是有效的JSON,但至少一些YAML解析器可以处理它,这可能对您可能正在消费输入的链中的下一步可用,甚至比通过jq管道更容易

例如Python的pyyaml(常见的基于第三方利比亚语法的解析器)可以直接处理这个

>>> s = """{
...   name: '',
...   success: false,
...   error: '',
...   data: {
...     video: ''
...   }
... }"""
>>> yaml.safe_load(s)  # returns a Python dictionary
{'name': '', 'success': False, 'error': '', 'data': {'video': ''}}

我为1-line buff提供了这个相当粗糙的解决方案

python3 -c "import sys,json,yaml; print(json.dumps(yaml.safe_load(''.join([x for x in sys.stdin][2:]))))"

importslibs
读取stdin
切片前两行[2:]
重新连接.join
解析为yaml到字典
将字典字符串化为json

完整的示例(没有用cat来演示从管道消费)

cat << EOF | python3 -c "import sys,json,yaml; print(json.dumps(yaml.safe_load(''.join([x for x in sys.stdin][2:]))))" | jq
Successes: 0
Failures: 1
{
name: '',
success: false,
error: '',
data: {
video: ''
}
}
EOF
{
"name": "",
"success": false,
"error": "",
"data": {
"video": ""
}
}

如果你只是想检查json是否有效,你可以这样做:

jq < foo.json > /dev/null 2>&1
echo $?

如果foo.json中的json无效,则$?将包含不相等的0。如果$? == 0——,则json是有效的。

BTW:这不仅仅是因为SuccessFailures键(这是json对象的外部),你的json是无效的-也所有的键和字符串值必须引号(用双引号)。例如,一个有效的版本应该是:

{
"Successes": 0,
"Failures": 1,
"name": "",
"success": false,
"data": {
"video": ""
}
}

要显示文件中除前两行以外的所有内容,可以使用以下命令:

( read; read; cat ) <foo.json

这将产生

{
name: '',
success: false,
error: '',
data: {
video: ''
}
}

但与你的说法相反,这不是有效的JSON,jq也不能使用它。如果这是您的最终目标,请使用hjson将该JS转换为JSON,如@peak所示。

以下是对标题中描述的任务的响应:

提取JSON文件的有效部分

给定一个文件,其中每个感兴趣的JSON实体都有一个类型,而不是"字符串";并且在单行上,有一个jq解决方案可以提取它们:

jq -nR 'inputs | fromjson? | select(type!="string")' input.txt

下面的变体也可能令人感兴趣:

jq -nR 'inputs | fromjson?' input.txt

最新更新