メインコンテンツへ移動

クエリ文字列からJSONへ

このコンバータは、ブラウザ内でURLクエリ文字列を構造化されたJSONにデコードします。値はパーセントデコードされ、+はスペースとして扱われます。重複キーは配列になり、a[b]=c形式のパスはネストされたオブジェクトに変換されます。空の値はnullとしてデコードされます。不正なパーセントエンコードは、位置を指定して拒否されます。何もアップロードされません。

端末内で処理

クエリ文字列からJSONへとは

クエリ文字列は一見すると意味不明に見えます――アンパサンド、イコール、パーセントエスケープ—ですが、それは一種のレコードであり、レコードには構造が与えられるべきです。このデコーダはクエリ文字列をJSONオブジェクトに変換します:各=の左側をキー、右側をデコードした値とし、重複キーは配列に収集され、a[b]=c形式のパスはネストされたオブジェクトに折りたたまれます。これはこのサイトの「JSONをクエリ文字列に」コンバータの正反対の動作であり、ペアで往復変換が可能です。

2つの規約が重要であり、どちらも尊重されます。プラス記号はスペースを意味します—あらゆるフォーム、ブラウザ、サーバーが今でも使用しているapplication/x-www-form-urlencodedの習慣—一方、%2Bは実際のプラス記号としてデコードされます。また、値は文字列のままです:クエリ文字列には型情報が含まれないため、page=2は「2」として到着し、郵便番号が後で問題になるだろうという推測は行いません。

デコードは完全にこのブラウザタブ内で行われます。文字列はページ内のコードによって分割され、エスケープが解除されます。ページからリクエストは送信されず、Content-Security-Policyは送信接続を明確に禁止します。Networkパネルで確認したい場合はどうぞ—ページは静かで、その静寂こそがプライバシーの保証です。

解析しようとしている文字列を作るのは、姉妹ツールのJSONからクエリ文字列への変換の役割です。このデコーダが読み取るのと同じa[b]=c規約で出力します。

JSONの出力が怪しくなった場合—余分な括弧、欠落した引用符—は、それをJSON検証ツールに貼り付けると、問題の正確な文字位置が指摘されます。

デコードの実際の動作

このコンバータは、先頭の?の有無にかかわらずクエリ文字列を受け入れます。&で分割し、各ペアを最初の=で分割するため、キーには=が含まれるのはパーセントエンコードされている場合のみです—これはまさにこのペアの反対側にあるエンコーダが行うことです。次に、各ペアごとに:

  • デコード:キーと値はUTF-8としてパーセントデコードされ、値内の+はスペースとして読み取られます。
  • ネスト:キー内のブラケットセグメントはネストされたオブジェクトになります—user[name]は{"user": {"name": ...}}に、a[user][city]は2レベルネストされます。
  • 収集:一度以上現れるキーは、到着順の値の配列になります。一度だけ現れるキーはスカラーのままです。
  • 空:値が空または欠落しているペア(token=、または=のないトークン)はnullとしてデコードされます。

入力ごとの規約

以下のテーブルは、デコーダの契約の縮小版です—各行は実装上の偶然ではなく、文書化されたルールです:

入力ペアデコードされたJSON
page=2{"page": "2"}――文字列として、型の推測は行いません
tag=navy&tag=math{"tag": ["navy", "math"]}
user[name]=Ada{"user": {"name": "Ada"}}
q=a%20b{"q": "a b"}――%20がデコードされます
q=a+b{"q": "a b"}――+はスペースです
q=a%2Bb{"q": "a+b"}――エスケープされた+はそのままです
token={"token": null}

出力の形式

以下の作業例は、「サンプルを読み込む」ボタンが生成するのとまったく同じペアです:JSONをクエリ文字列にページが出力する文字列を読み取ったものです。pageが「2」のまま、adminが「true」のままになることに注意してください—URLが型について何も言及していないため、文字列のままです。数値にしたい場合は、プログラムの境界でスキーマに基づいて明示的にキャストし、先頭に0がある郵便番号が破損する推測に頼るべきではありません。

推測ではなく拒否

不正なエスケープは、デコードツールが静かにデータを破損させる原因となるため、このコンバータは推測する代わりに拒否します。パーセント記号は有効なエスケープを開始する必要があります—有効なUTF-8を形成する2つの16進数—で、それ以外の場合は名前付きエラーが返されます:

  • %ZZや%2――16進数ではないため、エラーはリテラルの%やドロップされたバイトを出力するのではなく、キーと文字位置を指定します。
  • %FF――単独で存在する――16進数的には有効ですが有効なUTF-8ではないため、下流で文字化けとして送られるのではなく拒否されます。
  • 文字列末尾の裸の%――切り捨てられたエスケープなので、推測するのではなくソースを修正できるよう位置を指定して拒否されます。

よくある質問

クエリ文字列のデコードはどこかにアップロードしますか?

いいえ。文字列はページ内のJavaScriptによってこのブラウザタブ内で分割され、デコードされます。ページはデータを送信するAPIエンドポイントを定義しておらず、そのContent-Security-Policyは送信リクエストをブロックするため、コードが試みようとするものも何もアップロード先がありません。DevToolsを開き、文字列を変換してみてください—Networkパネルは空のままです。主張は一目で検証されます。

なぜすべての値が文字列なのですか?

クエリ文字列には型情報が含まれないからです:page=2はURLに関しては文字'2'と'2'の2文字です。デコーダは推測を拒否するため、2は「2」のまま、trueは「true」のままです—これはエンコーダ側も同じ方針です。スキーマがわかっている場所でキャストしてください。先頭に0がある郵便番号が数値2134になってしまうのは、推測が問題を引き起こす典型的な理由です。

デコード時に+は何を意味しますか?

スペースです。これはブラウザとサーバーが数十年間使用してきたapplication/x-www-form-urlencodedの規約であり、実際のクエリ文字列のほとんどはフォームから生成されます。リテラルの+は%2Bとしてパーセントエンコードされて到着する必要があります—このサイトのエンコーダはそのように出力し、両方の表記はここで同一にデコードされます。逆方向も一貫しています:スペースは%20として、プラスは%2Bとして送信されます。

重複キーはどのように処理されますか?

複数回現れるキーは、到着順の値の配列になります:tag=navy&tag=mathは{"tag": ["navy", "math"]}を生成します。一度だけ現れるキーはスカラーのままです。これはRackとNodeのqsパーサーの動作と一致しており、これはこのサイトのエンコーダの正確な逆です。エンコーダは配列の要素ごとにキーを繰り返し出力します。

a[b]=c表記はどのようにデコードされますか?

ブラケットセグメントはネストされたオブジェクトになります:user[name]=Adaは{"user": {"name": "Ada"}}にデコードされ、a[user][city]は2レベルネストされます。数値セグメントは文字列キーのままです—a[0]はキー「0」になります—なぜなら、インデックスから配列を推測することは、このデコーダが行わない推測だからです。リテラルのブラケットとその%5B/%5Dエスケープ形式の両方が受け入れられます。なぜなら、エンコーダはその点で異なる動作をする場合があるからです。

値がないペアはどうなりますか?

空の値—token=、または=のない単独のトークン—は空文字列ではなくnullとしてデコードされます。これは意図的にこのサイトの「JSONをクエリ文字列に」コンバータの逆であり、nullは空値として出力されるため、nullは往復変換で完全に保持されます。空文字列と欠落した値を区別する必要がある場合、クエリ文字列ではその違いを基本的に表現できません。