简体   繁体   English

使用JQ创建新的object,其中键来自一个object,值来自另一个

[英]Use JQ to create new object where the key comes from one object and the value comes from another

I have the following input:我有以下输入:

{
  "Columns": [
    {
      "email": 123,
      "name": 456,
      "firstName": 789,
      "lastName": 450,
      "admin": 900,
      "licensedSheetCreator": 617,
      "groupAdmin": 354,
      "resourceViewer": 804,
      "id": 730,
      "status": 523,
      "sheetCount": 298
    }
  ]
}
{
  "Users": [
    {
      "email": "abc@def.com",
      "name": "Abc Def",
      "firstName": "Abc",
      "lastName": "Def",
      "admin": false,
      "licensedSheetCreator": true,
      "groupAdmin": false,
      "resourceViewer": true,
      "id": 521,
      "status": "ACTIVE",
      "sheetCount": 0
    },
    {
      "email": "aaa@bbb.com",
      "name": "Aaa Bob",
      "firstName": "Aaa",
      "lastName": "Bob",
      "admin": false,
      "licensedSheetCreator": true,
      "groupAdmin": false,
      "resourceViewer": false,
      "id": 352,
      "status": "ACTIVE",
      "sheetCount": 0
    }
  ]
}

I need to change the key for all key value pairs in users to match the value in Columns, like so:我需要更改用户中所有键值对的键以匹配列中的值,如下所示:

{
  "Columns": [
    {
      "email": 123,
      "name": 456,
      "firstName": 789,
      "lastName": 450,
      "admin": 900,
      "licensedSheetCreator": 617,
      "groupAdmin": 354,
      "resourceViewer": 804,
      "id": 730,
      "status": 523,
      "sheetCount": 298
    }
  ]
}
{
  "Users": [
    {
      123: "abc@def.com",
      456: "Abc Def",
      789: "Abc",
      450: "Def",
      900: false,
      617: true,
      354: false,
      804: true,
      730: 521,
      523: "ACTIVE",
      298: 0
    },
    {
      123: "aaa@bbb.com",
      456: "Aaa Bob",
      789: "Aaa",
      450: "Bob",
      900: false,
      617: true,
      354: false,
      804: false,
      730: 352,
      523: "ACTIVE",
      298: 0
    }
  ]
}

I don't mind if I update the Users array or create a new array of objects.我不介意我是更新用户数组还是创建一个新的对象数组。 I have tried several combinations of with entries, to entries, from entries, trying to search for keys using variables but the more I dive into it, the more confused I get.我尝试了几种组合,包括条目、条目、条目、尝试使用变量搜索键,但我越深入,就越困惑。

Elements of a stream are processed independently. stream 的元素是独立处理的。 So we have to change the input.所以我们必须改变输入。

We could group the stream elements into an array.我们可以将 stream 个元素分组到一个数组中。 For an input stream, this can be achieved using --slurp / -s .对于输入 stream,这可以使用--slurp / -s来实现。 [1] [1]

jq -s '
   ( .[0].Columns[0] | map_values( tostring ) ) as $map |
   (
      .[0],
      (
         .[1:][] |
         .Users[] |= with_entries(
            .key = $map[ .key ]
         )
      )
   )
'

Demo on jqplay jqplay上的演示

Alternatively, we could use --null-input / -n in conjunction with input and/or inputs to read the input.或者,我们可以将--null-input / -ninput和/或inputs结合使用来读取输入。

jq -n '
   input |
   ( .Columns[0] | map_values( tostring ) ) as $map |
   (
      .,
      (
         inputs |
         .Users[] |= with_entries(
            .key = $map[ .key ]
         )
      )
   )
'

Demo on jqplay jqplay上的演示

Note that your desired output isn't valid JSON. Object keys must be strings.请注意,您所需的 output 无效 JSON。Object 键必须是字符串。 So the above produces a slightly different document than requested.因此,上面生成的文档与请求的文档略有不同。

Note that I assumed that .Columns is always an array of one exactly one element.请注意,我假设.Columns始终是一个只有一个元素的数组。 This is a nonsense assumption, but it's the only way the question makes sense.这是一个无意义的假设,但这是问题有意义的唯一方式。


  1. For a stream the code generates, you could place the stream generator in an array constructor ( [] ).对于代码生成的 stream,您可以将 stream 生成器放在数组构造函数 ( [] ) 中。 reduce can also be used to collect from a stream. For example, map(... ) can be written as [.[] |... ] and as reduce.[] as $_ ( []; . + [ $_ |... ] ) . reduce也可用于从 stream 中收集数据。例如, map(... )可写为[.[] |... ]reduce.[] as $_ ( []; . + [ $_ |... ] )

The following has the merit of simplicity, though it does not sort the keys.下面的代码具有简单的优点,尽管它没有对键进行排序。 It assumes jq is invoked with the -n option and of course produces a stream of valid JSON objects:它假定使用 -n 选项调用 jq,当然会生成一个 stream 的有效对象 JSON:

input
| . as $Columns
| .Columns[0] as $dict
| input # Users
| .Users[] |= with_entries(.key |= ($dict[.]|tostring))
| $Columns, .

If having the keys sorted is important, then you could easily add suitable code to do that;如果对键进行排序很重要,那么您可以轻松地添加合适的代码来做到这一点; alternatively, if you don't mind having the keys of all objects sorted, you could use the -S command-line option.或者,如果您不介意对所有对象的键进行排序,则可以使用 -S 命令行选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM