文字列の生文字を使用したJSON変換

文字列の生文字を使用したJSON変換

違法なJSONを生成するツールに問題があります。

一部のJSON文字列には00から1fの範囲の文字が含まれています。したがって、これらの文字を\u00xx文字列から適切にエスケープされた値に変換したいと思います。

私ができる最善は:

cat test2.json | jq -aR . | sed -e 's/\\"/"/g' -e 's/^"\(.*\)"$/\1/' | jq

説明する:

jq -aR                    reads the data as raw input and converts
                          the whole thing into a single string.
                          This converts all control characters into
                          the correct form => \u00xx

sed -e 's/^"\(.*\)"$/\1/' Removes the quotes from the beginning and end.

sed -e 's/\\"/"/g'        Looks for escaped quotes and removed the quotes.

jq                        Just makes it pretty again at the end.
                          Also makes sure it is valid JSON.

いくつかの問題が見つかりました(幸いなことに私には影響を及ぼす問題はありません)。

  1. 文字列に含まれる '\n' が正しく処理されませんでした。
  2. これで、すべてのエスケープ文字をダブルエスケープできます。
  3. 私が考慮していない他のものがあるかもしれません。

一部のテストデータは、次のように生成できます。

echo -e "{ \"data\": \"XX\001YY\"}" > test2.json

それからテストしました。

cat test2.json | jq -aR . | sed -e 's/\\"/"/g' -e 's/^"\(.*\)"$/\1/' | jq

生成する:

{
  "data": "XX\u0001YY"
}

newline文字列の内部にあるとき => '\n' => '\x0a' が正しく処理されないことに気づきました。

答え1

Perlを使用して、すべてのC0コントロールを16進エスケープに置き換えることができます。

perl -pe 's/([\x01-\x1f])/sprintf("\\u%04x", ord($1))/eg' < test.json

これ

  1. プログラムをループとして実行し、最後に結果をsedスタイルで印刷します(perl -pe)。
  2. 01-1fの範囲内のすべてのバイトと一致(s/([\x01-\x1f])/... g
  3. バイトの序数値の計算( ord($1))
  4. sprintf("\\u%04x", ord($1))/e一致するバイトを()の結果に置き換えます

これにより、一致するバイト位置に\u0001、、\u0002...が挿入されます。\u001f

それ〜するすべての改行は同じ方法でエスケープされているため、ファイルに引用されていない改行があると中断されます(テキストファイルには少なくとも1つの終了改行がありますが、これは機械的に前後に削除できます)。この場合は[\x01-\x09\x0b-\x1f]スキップしても失敗します。はい引用符の中に実際の改行文字があります。

ファイルに引用符付き改行文字と引用符付き改行文字の両方が含まれている場合、これらの文脈のない置換は機能しません。ファイルをそのまま受け入れる無料のJSONパーサーが必要なので、エスケープする必要があるファイルとそうでないファイルがわかります。そのうちの1つについてはよくわかりません。

関連情報