1

我有以下 JSON。我想根据他们的角色获取键值对对象。在此示例中,有 3 个角色(Presenter、Approver、Customer),但可以有更多,因为它是动态的。

JSON

{
   "Presenter Name": "Roney",
   "Presenter Email": "roney@domain.com",
   "Approver Name": "Tim",
   "Approver Email": "tim@domain.com",
   "Customer Name": "Alex",
   "Customer Email": "alex@domain.com",   
   "Invoice": "001",
   "Date": "2022-02-14"   
}

使用 jq、map、

{
    "Presenter": {
      "email_address": "roney@domain.com",
      "name": "Roney",
      "role": "Presenter"
    },
    "Approver": {
      "email_address": "tim@domain.com",
      "name": "Tim",
      "role": "Approver"
    },
    "Customer": {
      "email_address": "alex@domain.com",
      "name": "Alex",
      "role": "Customer"
    }
}

我已经尝试过,但没有得到下一步该做什么。请指教。

to_entries |map( { (.key): { name: .value, email_address:.value, role: .key} } ) | add

4

3 回答 3

3

split是空格字符的键,同时丢弃任何没有其中的项目。然后它相应地将三个字段分配给它们的值,reduce用于组合分组。

to_entries
| map(.key |= split(" ") | select(.key[1]))
| reduce group_by(.key[0])[] as $g ({};
    .[$g[0].key[0]] = (
      INDEX($g[]; .key[1]) | {
        email_address: .Email.value,
        name: .Name.value,
        role: .Name.key[0]
      }
    )
  )
{
  "Approver": {
    "email_address": "tim@domain.com",
    "name": "Tim",
    "role": "Approver"
  },
  "Customer": {
    "email_address": "alex@domain.com",
    "name": "Alex",
    "role": "Customer"
  },
  "Presenter": {
    "email_address": "roney@domain.com",
    "name": "Roney",
    "role": "Presenter"
  }
}

演示

于 2022-02-13T19:16:39.153 回答
2

这是另一种更短的方法,它不使用group_by. reduce相反,如果键遵循空格分隔的角色键模式,这将直接迭代初始对象并立即相应地设置所有字段。

reduce (to_entries[] | .key /= " ") as {key: [$role, $key], $value} ({};
  if $key then
    .[$role] += {({Email: "email_address", Name: "name"}[$key]): $value, $role}
  else . end
)
{
  "Presenter": {
    "name": "Roney",
    "role": "Presenter",
    "email_address": "roney@domain.com"
  },
  "Approver": {
    "name": "Tim",
    "role": "Approver",
    "email_address": "tim@domain.com"
  },
  "Customer": {
    "name": "Alex",
    "role": "Customer",
    "email_address": "alex@domain.com"
  }
}

演示

于 2022-02-14T01:12:23.093 回答
1
{ "Name": "name",  "Email": "email_address" } as $key_map |
to_entries |
map (
   ( .key | split(" ") | select( length == 2 ) ) as [ $role, $raw_key ] |
   [ $role, "role",             $role  ],
   [ $role, $key_map[$raw_key], .value ]
) |
reduce .[] as [ $role, $key, $val ] ( {}; .[ $role ][ $key ] = $val )

jqplay上的演示


在上面,我们首先使数据统一。具体来说,我们首先生成以下内容:

[
   [ "Presenter", "role",          "Presenter"        ],
   [ "Presenter", "name",          "Roney"            ],
   [ "Presenter", "role",          "Presenter"        ],
   [ "Presenter", "email_address", "roney@domain.com" ],
   [ "Approver",  "role",          "Approver"         ],
   [ "Approver",  "name",          "Tim"              ],
   [ "Approver",  "role",          "Approver"         ],
   [ "Approver",  "email_address", "tim@domain.com"   ],
   [ "Customer",  "role",          "Customer"         ],
   [ "Customer",  "name",          "Alex"             ],
   [ "Customer",  "role",          "Customer"         ],
   [ "Customer",  "email_address", "alex@domain.com"  ]
]

有多余的信息,但这并不重要。

然后,最后的简单reduce构建所需的结构。


.key | split(" ") | select( length == 2 )

可以换成更安全的

.key | match("^(.*) (Name|Email)$") | .captures | map( .string )
于 2022-02-13T22:20:14.400 回答