将特定模式后的多行附加到多个JSON文件

时间:2017-07-11 17:00:20

标签: javascript json bash shell jq

我有几个看起来像这样的JSON文件

{
"$schema": "someURL",
  "id": "someURL",
  "type": "object",
  "properties": {
    "copyright": {
      "id": "someURL",
      "type": "object",
      "description": "Setup for copyright link",
      "properties": {
        "translation": {
          "id": "someURL",
          "type": "string",
          "description": "someString"
        },
        "url": {
          "id": "someURL",
          "type": "string",
          "description": "someString"
        }
      }...

我需要做的是为removable的每个实例中的每个项添加appendableproperties属性,并将它们设置为true。所以输出应该是这样的:

{
    "$schema": "someURL",
      "id": "someURL",
      "type": "object",
      "properties": {
        "copyright": {
          "removable": true,
          "appendable": true,
          "id": "someURL",
          "type": "object",
          "description": "Setup for copyright link",
          "properties": {
            "translation": {
              "removable": true,
              "appendable": true,
              "id": "someURL",
              "type": "string",
              "description": "someString"
            },
            "url": {
              "removable": true,
              "appendable": true,
              "id": "someURL",
              "type": "string",
              "description": "someString"
            }
          }...

有没有办法实现自动化?在编写一个脚本时,会自动在属性中的每个项目下面添加这些字段吗?

2 个答案:

答案 0 :(得分:0)

使用NodeJS我会写这样的东西:

const fs = require('fs');
let args = process.argv.map(val=>val));
let contents = fs.readFileSync(args[0]);

let obj = JSON.parse(contents);

const proc = (obj, append)=>{
    for (prop in obj)
    {
        let p = obj[prop];
        if (p.constructor!=Object)
            continue;
        if (append)
        {
            p.removable = true;
            p.appendable = true;
        }
        proc(p, prop=='properties');
    }
};

console.log(JSON.stringify(proc(obj), null, 2));

然后在bash中执行:

find -name '*\.json' -exec 'node proc.js {} > {}.new'

我没有测试任何东西,一切都来自我的脑袋,但起点应该足够好。

答案 1 :(得分:0)

鉴于您希望将更新应用于具有名为"属性"的密钥的所有对象,无论它们出现在何处,我都倾向于使用walk/1。在任何情况下,为了使事情更清晰,可能更容易,如果输入的类型正确,定义一个将应用更新的辅助函数会很有帮助:

def update(obj):
  if type == "object" and has("properties")
  then .properties |= with_entries( .value += obj )
  else .
  end;

使用walk/1,解决方案现在变得微不足道了:

walk( update({removable: true, appendable: true}) )

Robustification

改变"然后"可能是谨慎的做法。以上行:

then .properties |= 
  with_entries( if .value | type == "object"
                then .value += obj
                else . end)