根据元素所属的类别标记元素

时间:2019-03-10 11:48:37

标签: json dictionary jq

我有object_count.json元素流,看起来像:

{
    "name":"apple",
    "count":10
}
{
    "name":"potato",
    "count":18
}
{
    "name":"stone",
    "count:7
}

与流分开,我有两个文件,每个文件都列出了其类的对象的名称:

cat fruits.txt
  apple
  peach

cat vegetables.txt
  potato
  tomato

如何构造一个流,其中object_count.json中的每个对象都具有各自的类名?即:

{
    "name":"apple",
    "count":10
    "class":"fruit"
}
{
    "name":"potato",
    "count":18
    "class":"vegetable"
}
{
    "name":"stone",
    "count":7
    "class":"other"
}

我们可以假设object_count.json中每个对象名称只有一个条目。


我最喜欢的解决方案是:

  • 可以很好地运行3、4和更多类-每个类仍在单独的文件中列出;每个类都经过硬编码就可以了
  • object_count.json被视为输入流,而{fruits|vegetables}.txt作为单独的--rawfile自变量
  • 提供

JQ报告的版本:

 $ jq --version
 jq-1.6

我设法将类文件作为命令行参数来提供,但是未能找到合适的join / in表达式来解决问题:

cat object_count.json | jq -n --rawfile fruits "fruits.txt" '($fruits | split("\n") | map(select(. != "")) | sort) as $frts | inputs'

2 个答案:

答案 0 :(得分:1)

根据更新后的问题,这是一种避免混淆object_count.json内容的解决方案。

dictionary.jq

def trim: sub("^ +"; "") | sub(" +$"; "");

def dictionary(s):
  reduce (s | trim | select(length>0)) as $in ({};
     (input_filename | sub(".txt";"") | sub("s$";"")) as $class
     | .[$in] = $class );

dictionary(inputs) 

调用

jq --argfile class <(jq -n -R -f dictionary.jq *.txt)  '
 .class = ($class[.name] // "other")'  object_count.json

后记

可能需要使用“ other”作为默认类名,但是如果不是这样,则在这种情况下,最好使用流程并使用JSON的null作为默认类名。对象的键。

答案 1 :(得分:0)

[这是对原始问题的答复。它允许任意多个“类”文件,并且只需要一次调用jq。有关不涉及“吸引” JSON流的解决方案,请参阅此页面上的其他地方。]

这里最棘手的部分是管理未知数量的.txt文件。在这里,我们假设我们可以编写'* .txt'来捕获它们,因此jq的调用将如下所示:

jq -n -R -f program.jq --slurpfile input object_count.json *.txt

要构建字典,我们将使用以下辅助函数:

def trim: sub("^ +"; "") | sub(" +$"; "");

# construct the dictionary
def dictionary(s):
  reduce (s | trim | select(length>0)) as $in ({};
     (input_filename | sub(".txt";"") | sub("s$";"")) as $class
     | .[$in] = $class );

现在任务减少到以下三行:

dictionary(inputs) as $class
| $input[]
| .class = ($class[.name] // "other")