代码之家  ›  专栏  ›  技术社区  ›  ImranRazaKhan

将json文件拆分为父文件和多个子文件

  •  0
  • ImranRazaKhan  · 技术社区  · 5 年前

    我有一个将来会增长的json文件,所以我想把它拆分为一个文件夹中的父文件和子文件,并引用父文件中的所有子文件,这样我就可以管理多个文件而不是一个大文件。我正在使用此文件进行配置

    主.json

    {
        "store": {
            "book": [
                {
                    "category": "reference",
                    "author": "Nigel Rees",
                    "title": "Sayings of the Century",
                    "price": 8.95
                },
                {
                    "category": "fiction",
                    "author": "Evelyn Waugh",
                    "title": "Sword of Honour",
                    "price": 12.99
                }
            ],
            "bicycle": {
                "color": "red",
                "price": 19.95
            }
        },
        "expensive": 10
    } 
    

    我想像下面这样分开

    父级.json

    {
        "store": {
            "book": [
                "$ref": "book1.json",
                "$ref": "book2.json"
            ],
            "bicycle": {
                "color": "red",
                "price": 19.95
            }
        },
        "expensive": 10
    }
    

    图书1.json

    {
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
    }
    

    我试图显示父文件,但它给出的错误,我想要父级.json应显示为主.json

    # jq . parent.json
    parse error: ':' not as part of an object at line 10, column 19
    
    0 回复  |  直到 5 年前
        1
  •  2
  •   sshine    5 年前

    关于@Dmitry的观点(即 [ "$ref": "book1.json" ] 不是有效的JSON),为什么不改为

    [
      { "$ref": "book1.json" },
      { "$ref": "book2.json" },
      ...
    ]
    

    除此之外,您需要的是一个生成多个文件的程序,其中之一是父级.json剩下的都是书 n .json文件。因为 jq 只能通过一个流提供输出,您可以为每个输出文件生成一行压缩的JSON,第一行是父级.json,剩下的每本书 n .json文件。然后,您必须对每一行进行后期处理并通过管道将其传输到适当的文件中,然后您可以在该点解压缩该行。

    1. 产生多条线,
    $ jq -c '.store.book as $books | .store.book = [
          { "$ref": "book\(range(1; $books | length + 1)).json" } ], $books[]' Main.json
    {"store":{"book":[{"$ref":"book1.json"},{"$ref":"book2.json"}],"bicycle":{"color":"red","price":19.95}},"expensive":10}
    {"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95}
    {"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}
    
    1. 将这些行放入各自的文件中,解压缩每一行,
    $ jq -c '...' Main.json | (
          IFS= read -r parent
          jq . <<< "$parent" > Parent.json
    
          i=1
          while IFS= read -r book
          do
            jq . <<< "$book" > "book$i.json"
            i=$(($i+1))
          done
      )
    

    我的sh有点生锈了,正在储藏 read


    更新: 以托尔出色的解决方案的精神,他将父级.json还有书 n .json分为两个任务,并用 split 这似乎很合适,我想我应该看看我能不能做些类似的事情:

    genbooks() {
      jq -c '.store.book[]' |
      perl -nlE '$i++; open my $fh, "|jq . >book$i.json"; say $fh $_; close $fh'
    }
    
        2
  •  1
  •   Community Mike Kinghan    4 年前

    你可以一次完成 jq coreutils ,例如,定义如下两个函数:

    genparent() {
      jq '.store.book = [ { "$ref": "book\(range(1; .store.book | length + 1)).json" } ]' > Parent.json
    }
    
    genbooks() {
      jq -c '.store.book[]'           |
      split --numeric-suffix=1        \
            --suffix-length=1         \
            --additional-suffix=.json \
            --filter='jq . > $FILE'   \
            --lines=1 - book
    }
    

    然后像这样运行:

    <Main.json tee >(genparent) >(genbooks) > /dev/null
    ls
    

    输出:

    book1.json  book2.json  Main.json  Parent.json
    

    父级.json

    {
      "store": {
        "book": [
          {
            "$ref": "book1.json"
          },
          {
            "$ref": "book2.json"
          }
        ],
        "bicycle": {
          "color": "red",
          "price": 19.95
        }
      },
      "expensive": 10
    }
    

    图书1.json

    {
      "category": "reference",
      "author": "Nigel Rees",
      "title": "Sayings of the Century",
      "price": 8.95
    }
    

    图书2.json

    {
      "category": "fiction",
      "author": "Evelyn Waugh",
      "title": "Sword of Honour",
      "price": 12.99
    }