jqは同じキーの値を配列にマージしますか?

jqは同じキーの値を配列にマージしますか?

配列の1:1マッピングとしてJSONにエクスポートされたSQL結果セットがあります。

例えば

[
  {
    "subject": "Accounting",
    "level": "A Level"
  },
  {
    "subject": "Accounting",
    "level": "IB"
  },
  {
    "subject": "Accounting",
    "level": "University"
  },
  {
    "subject": "Accounting",
    "level": "GCSE"
  },
  {
    "subject": "Accounting",
    "level": "Mentoring"
  },
  {
    "subject": "Accounting",
    "level": "13 Plus"
  },
  {
    "subject": "Accounting",
    "level": "11 Plus"
  },
etc.....

次のようにレベルをトピックキーに結合したいと思います。

[
   "Accounting": ["A Level", "IB", "University"],
   "Foo": ["Foo Intro", "Foo Basics", "Intermediate Foo"] 
]

メモ:匿名オブジェクトなし

jqを使用してこれをどのように達成できますか?

答え1

与えられた

$ jq '.' file.json
[
  {
    "subject": "Accounting",
    "level": "A Level"
  },
  {
    "subject": "Foo",
    "level": "IB"
  },
  {
    "subject": "Accounting",
    "level": "University"
  },
  {
    "subject": "Foo",
    "level": "GCSE"
  },
  {
    "subject": "Accounting",
    "level": "Mentoring"
  },
  {
    "subject": "Accounting",
    "level": "13 Plus"
  },
  {
    "subject": "Foo",
    "level": "11 Plus"
  }
]

それではお金を借りてください。要約データを使用してjq配列の外観を変更する

$ jq 'reduce .[] as $d (null; .[$d.subject] += [$d.level])' file.json 
{
  "Accounting": [
    "A Level",
    "University",
    "Mentoring",
    "13 Plus"
  ],
  "Foo": [
    "IB",
    "GCSE",
    "11 Plus"
  ]
}

注:外部レイヤーは配列ではないオブジェクトです(予想される出力で見られるように、有効なJSONではないようです)。

答え2

これをどのように行うのかわかりませんjq。 (私は、次のような単一目的ツールを学ぶよりも、Perlのような汎用言語で何かを書く方が簡単だと思いますjq... jsonデータをより頻繁に使用すると価値があるかもしれません。)最も基本的な使い方よりも多く学ぶ時間です。しかし、Perlを使うと簡単です。JSON基準寸法。

#!/usr/bin/perl
use strict;
use JSON;

# hash-of-arrays to hold an array of "level"s for each "subject"
my %merged;

# slurp the input into scalar string variable $text
my $text; { local $/; $text=<> }

my $json = JSON->new->allow_nonref;
my $data = $json->decode($text);  # parse json text into $data arrayref

# loop over each row of $data and insert into %merged
foreach my $row (@$data) {
  my $key = $row->{subject};
  my $val = $row->{level};

  push @{ $merged{$key} }, $val;
};

# pretty-print %merged as json
print $json->pretty->encode(\%merged), "\n";

出力例:

$ ./merge-json.pl input.json 
{
   "Accounting" : [
      "A Level",
      "IB",
      "University",
      "GCSE",
      "Mentoring",
      "13 Plus",
      "11 Plus"
   ],
   "Foo" : [
      "Foo Intro",
      "Foo Basics",
      "Intermediate Foo"
   ]
}

Debian、Ubuntuなどを実行している場合は、次のコマンドを使用してJSONモジュールをインストールできますsudo apt-get install libjson-perl libjson-xs-perl(これにより、Perlのデフォルトバージョンをインストールする必要があります)そしてCバージョンモジュールのコンパイルが速くなり、JSON::XS)。他のディストリビューションでも動作できます。それ以外の場合は、を使用してインストールしてくださいcpan

答え3

とは異なるアプローチスチールドライバーキーごとにデータをグループ化subjectし、levelその配列の下のすべての値を収集しますsubject

以下は、steeldriverと同じテストデータを使用します。

$ jq 'group_by(.subject) | map({ (first.subject):  map(.level) }) | add' file
{
  "Accounting": [
    "A Level",
    "University",
    "Mentoring",
    "13 Plus"
  ],
  "Foo": [
    "IB",
    "GCSE",
    "11 Plus"
  ]
}

最後に、以前addに作成された配列の要素をマージしますmap()

関連情報