JSONエスケープの入力方法は何ですか?

JSONエスケープの入力方法は何ですか?

APIを介してgithub gistにデータを送信するツールを開発しようとしています。問題は、github apiがポイントを1行contentとして扱い、すべてのエスケープシーケンスが次のように文字通り書き込まれることです。

{
  "test.txt": {
    "filename": "test.txt",
    "type": "text/plain",
    "language": "Shell",
    "raw_url": "https://gist.githubusercontent.com/jessebutryn/5c8b2a95b4b016e2fa33edee294c732b/raw/474f72ad32c843c18e9a61a228a31df6b85a8da1/test.txt",
    "size": 96,
    "truncated": false,
    "content": "#!/bin/sh\n\n# comment\nfunc () {\n\tfor ((i=1;i<10;i++)); do\n\t\t:\n\tdone\n}\n\nprintf '%s\\n' Foo bar baz\n"
  }
}

内容は次のように表示されます。

#!/bin/sh

# comment
func () {
    for ((i=1;i<10;i++)); do
        :
    done
}

printf '%s\n' Foo bar baz

これは次のように変換する必要があります。

#!/bin/sh\n\n# comment\nfunc () {\n\tfor ((i=1;i<10;i++)); do\n\t\t:\n\tdone\n}\n\nprintf '%s\\n' Foo bar baz\n

これを一度に実行できるツールはありますか?そうでない場合は、sed標準のUNIXツールを使用してこれを行う方法を知っている人はいますか?


注:元のテキストのリテラルエスケープシーケンスはgithubが解釈できないようにエスケープする必要があります(ただし、この質問で解決する必要はないマイナーな問題ですが、次の場合には良いでしょう)。

つまり:

printf '%s\n' Foo bar baz

になる:

printf '%s\\n' Foo bar baz

答え1

jq -R -s '.' < datafile

datafileこれにより、すべての内容が文字列として読み取られ、jqはそれをJSON文字列として印刷します。内容をテンプレートに直接置き換えるのに適した引用文字列を提供しますdatafile。データは、以下を含む正しいJSONによって参照されます。RFC 7159エスケープJSONは文字列リテラルが複数行にまたがることを許可しないため、およびを1つの大きな行に使用します。


テンプレートJSONファイルを使用してjq内の文書全体を組み合わせることもできます。

jq --arg f "$(cat datafile)" '.["test.txt"].content = $f' < template.json

最新バージョンには、コマンド置換を使用する代わりにファイルを文字列としてロードするオプションがjqあります。また、を使って内容を変更することもできます。--rawfile f datafile-R --slurp --slurpfile t template.json datafilet["test.txt"].content = .

答え2

他のJSONに含めるには、いくつかのJSONをエスケープする必要があり、非常に簡単な解決策があります。

$ jq @json <<< '{"Hello": "World"}'
"{\"Hello\":\"World\"}"

答え3

既存のJSONドキュメントがあり、file.jsonコンテンツを正しい場所に挿入したい場合はjq

jq --rawfile content test.txt '."test.txt".content |= $content' file.json

コンテンツをbase64でエンコードする必要がある場合:

base64 test.txt | jq --rawfile content /dev/stdin '."test.txt".content |= $content' file.json

joおおよその合計出力のメタデータ)を使用して、最初からJSONを構築します。statfile

#!/bin/sh

gist_url='some url'
filename=test.txt

jo -p "$filename"="$( jo \
        filename="$filename" \
        type="$( file -b --mime-type "$filename" )" \
        language="$( file -b "$filename" )" \
        raw_url="$gist_url" \
        size="$( stat -c %s "$filename" )" \
        truncated=false \
        content=@"$filename" )"

Unixに基づく調整statとユーティリティ(上記のLinuxオプションを使用)file

出力:

{
   "test.txt": {
      "filename": "test.txt",
      "type": "text/x-shellscript",
      "language": "POSIX shell script, ASCII text executable",
      "raw_url": "some url",
      "size": 108,
      "truncated": false,
      "content": "#!/bin/sh\n\n# comment\nfunc () {\n    for ((i=1;i<10;i++)); do\n        :\n    done\n}\n\nprintf '%s\\n' Foo bar baz"
   }
}

%"$filename"代わりに@"$filename"キーのbase64エンコーディング値を取得するには、次のようにしますcontent

{
   "test.txt": {
      "filename": "test.txt",
      "type": "text/x-shellscript",
      "language": "POSIX shell script, ASCII text executable",
      "raw_url": "some url",
      "size": 108,
      "truncated": false,
      "content": "IyEvYmluL3NoCgojIGNvbW1lbnQKZnVuYyAoKSB7CiAgICBmb3IgKChpPTE7aTwxMDtpKyspKTsgZG8KICAgICAgICA6CiAgICBkb25lCn0KCnByaW50ZiAnJXNcbicgRm9vIGJhciBiYXoK"
   }
}

関連情報