joを使用してシェルの連想配列からJSONオブジェクトを作成するには?

joを使用してシェルの連想配列からJSONオブジェクトを作成するには?

私は知っています連想配列からJSONを生成する方法しかし、それは私の問題ではありません。

次の連想配列があります。

declare -A aliases
aliases[Index]=components/Index/Exports
aliases[Shared]=components/Shared/Exports
aliases[Icons]=components/Icons/Exports

この連想配列を次のJSONに変換する必要があります。

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "Index": ["components/Index/Exports"],
            "Shared": ["components/Shared/Exports"],
            "Icons": ["components/Icons/Exports"],
        }
    }
}

joとを使用したいjq。しかし、ネストがわかりません。

私はこのコードを試しました:

jo -p compilerOptions[baseUrl]=. compilerOptions[paths]="$(jo -p a ${Aliases[@]})"

しかし、実行すらされません。

ベストアンサー1

考えられる解決策の1つは次のとおりです。

declare -A aliases
aliases[Index]=components/Index/Exports
aliases[Shared]=components/Shared/Exports
aliases[Icons]=components/Icons/Exports

jq -n --argjson n "${#aliases[@]}" '
        { compileroption: {
                baseurl: ".",
                paths:
                (
                        reduce range($n) as $i ({};
                                .[$ARGS.positional[$i]] = [$ARGS.positional[$i+$n]]
                        )
                )
        } }' --args "${!aliases[@]}" "${aliases[@]}"

jo連想配列を使用する代わりに、キーと値はコマンドの最後に位置引数aliasesとして渡されます(使用される場合は常に最後のオプションでなければなりません)。ユーティリティはキーと値を単一の配列として受け取ります。つまり、配列の最初の半分にキーが含まれ、配列の2番目の半分に対応する値が含まれます。jq--args--argsjq$ARGS.positional

式の本文は、jq出力オブジェクトを生成し、reduceゼロから始まる整数範囲で機能します。ここでは、配列の要素数です。この操作では、 :th パラメーターをキーとして使用し、 + :th パラメーターをその配列値の要素として使用して、位置パラメーターを 1 つずつ追加してオブジェクトを作成します。$n$naliasesreducepaths$i$i$n


jo連想配列の各キーと値のペアに対してリーフオブジェクトを作成する方法は少し異なります。

declare -A aliases
aliases[Index]=components/Index/Exports
aliases[Shared]=components/Shared/Exports
aliases[Icons]=components/Icons/Exports

for key in "${!aliases[@]}"; do
        jo "$key[]=${aliases[$key]}"
done

これにより、3つのオブジェクトが出力されます。

{"Icons":["components/Icons/Exports"]}
{"Index":["components/Index/Exports"]}
{"Shared":["components/Shared/Exports"]}

私たちはこれをこのように使用しているので、jo配列のキーにいくつかの明白な制限を適用します(=などを含めない場合があります[])。

私たちはこれを次jqのように使用できますjo

for key in "${!aliases[@]}"; do
        jq -n --arg key "$key" --arg value "${aliases[$key]}" '.[$key] = [$value]'
done

その後、それを読み取り、作成中のオブジェクトの正しい場所に追加できますjq

declare -A aliases
aliases[Index]=components/Index/Exports
aliases[Shared]=components/Shared/Exports
aliases[Icons]=components/Icons/Exports

for key in "${!aliases[@]}"; do
        jo "$key[]=${aliases[$key]}"
done |
jq -n '{ compileroptions: {
        baseURL: ".",
        paths: (reduce inputs as $item ({}; . += $item)) } }'

ここでの主な違いは、jqコンテンツをコマンドラインオプションとして渡すのではなく、JSONオブジェクトストリームに渡すことです。

おすすめ記事