質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

URL

URL(ユニフォームリソースロケータ)とは、インターネット上のリソース(Webページや電子メールの宛先等)を特定するための形式的な記号の並びの事を言う。

パラメータ

関数やプログラム実行時に与える設定値をパラメータと呼びます。

Q&A

解決済

2回答

6975閲覧

クエリパラメータの値として"="(イコール)や"&"(アンパサンド)を設定したい。

curveworks

総合スコア12

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

URL

URL(ユニフォームリソースロケータ)とは、インターネット上のリソース(Webページや電子メールの宛先等)を特定するための形式的な記号の並びの事を言う。

パラメータ

関数やプログラム実行時に与える設定値をパラメータと呼びます。

0グッド

1クリップ

投稿2022/04/11 11:29

編集2022/04/11 11:31

Javaにて、以下を設定項目とするWebAPIの呼び出しを実装中です。

  • 送信方式:POST
  • Content-Type:application/x-www-form-urlencoded
  • クエリパラメータ:キー1=値1&キー2=値2&キー3=値3

クエリパラメータの各値には"="や"&"が設定される可能性があるのですが、Content-Typeがapplication/x-www-form-urlencodedの場合、そもそも接続文字列として"="と"&"が使用されているため、これらを値として設定するには考慮が必要と考えております。

質問1: このような場合、そもそもエンコードにあたり考慮は必要でしょうか。
質問2: 考慮が必要である場合、どのようにクエリパラメータを作成すれば良いのでしょうか。

現在の実装

Java

1import org.apache.commons.codec.net.URLCodec.URLCodec; 2 3public request() { 4 String url = "http://webapi"; 5 StringBuilder sb = new StringBuilder(); 6 String value1 = "value1"; 7 String value2 = "hoge&fuga"; 8 String value3 = "foo=bar"; 9 sb.append("key1=").append("value1") 10 .append("&").append("key2=").append(value2) 11 .append("&").append("key3=").append(value3); 12 13 String enc = new URLCodec("URL-8").encode(sb.toString()); 14 15 HttpURLConnection conn; 16 conn = new URL(url).openConnection(); 17 conn.setRequestMethod("POST"); 18 conn.setDoOutput(true); 19 conn.setInstanceFollowRedirects(false); 20 conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); 21 conn.connect(); 22 try (PrintWriter pw = new PrintWriter( 23 new BufferedeWriter( 24 new OutputStreamWriter( 25 conn.getOutputStream(), "utf-8")))) 26 { 27 pw.print(enc); 28 } 29}

※例外処理は見やすさのため除外しています。
また、文字列をエンコードするのにapache commonsのURLCodecを使用しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

質問1: このような場合、そもそもエンコードにあたり考慮は必要でしょうか。

はい、必要です。

質問2: 考慮が必要である場合、どのようにクエリパラメータを作成すれば良いのでしょうか。

全体のクエリ文字列を一度に作ろうとするから難しくなります。それぞれのクエリパラメータ、すなわち「パラメータ名=値」のそれぞれを個別にエンコードし、複数のパラメータを配列もしくはリストで扱って、最後に&で連結するようにすれば考えることが局所化され、実装がシンプルになるかと思います。

以下はパラメータの名前と値をフィールドに持つQueryParamクラスで、オーバーライドしたtoStringメソッドの実行時にエンコードした「パラメータ名=値」をStringで返し、複数のパラメータをString.joinで連結して全体のクエリ文字列を生成するサンプルコードです。ちなみに質問者さんご提示のコード中、URLCodecのコンストラクタで指定していたキャラクターセットは"URL-8"ではなく"UTF-8"の誤りだと思いましたので、この部分は修正しています。("URL-8"だと私の環境ではencodeメソッドの実行時に例外がスローされました)

Java

1import org.apache.commons.codec.EncoderException; 2import org.apache.commons.codec.net.URLCodec; 3import java.util.List; 4import java.util.ArrayList; 5 6public class QueryParam { 7 private String name; 8 private String value; 9 10 public static final String CHARSET = "UTF-8"; 11 private static URLCodec codec = new URLCodec(CHARSET); 12 13 public static void main(String[] args) 14 throws EncoderException 15 { 16 System.out.println("start."); 17 18 // 複数のクエリパラメータを格納するリスト 19 List<String> parameters = new ArrayList<String>(); 20 21 // 1: "key1=value1" 22 parameters.add(new QueryParam("key1", "value1").toString()); 23 24 // 2: "キー2=日本語値2" 25 parameters.add(new QueryParam("キー2", "日本語値2").toString()); 26 27 // 3: パラメータ名と値に"=& "が含まれるパターン 28 parameters.add(new QueryParam("k3=& ", "v3=& ").toString()); 29 30 // "&"でつなげて全体のクエリー文字列を生成 31 String form = String.join("&", parameters); 32 System.out.println("query string: " + form); 33 } 34 35 public QueryParam(String name, String value) { 36 this.name = name; 37 this.value = value; 38 } 39 40 /* パラメータ名と値をそれぞれエンコードして文字列化 41 */ 42 @Override 43 public String toString() { 44 String result = null; 45 try { 46 result = codec.encode(name) + "=" + codec.encode(value); 47 } catch (EncoderException ex) { 48 // ※ 実製品では適切に例外ハンドリングしましょう 49 ex.printStackTrace(); 50 ; 51 } 52 return result; 53 } 54} 55

これを実行すると以下のようになります。読みづらいかもしれませんが、パラメータ名と値はエンコードした後に=で繋ぎ、それぞれのパラメータは&で連結されていることが分かると思います。

terminal

1start. 2query string: key1=value1&%E3%82%AD%E3%83%BC2=%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%80%A42&k3%3D%26+=v3%3D%26+

尚、Eclipse 上のJavaSE-11、Apache Commons Codec 1.15の「commons-codec-1.15.jar」で試しました。

投稿2022/04/15 10:28

dodox86

総合スコア9254

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

curveworks

2022/04/25 04:17

ご回答ありがとうございました。 自分の認識として、application/x-www/urlencodedでリクエストを送信する場合、=も&も含めてすべてエンコードする必要がある前提の頭になっていたことによる質問でした。 サンプルコードも丁寧に記載して頂き大変参考になりました。ありがとうございます。 (ご認識の通り"URL-8"は"UTF-8"の誤りでした。失礼いたしました。)
guest

0

RFC のどこかには書いてあるわけですが、例えば
URLのクエリーパラメータでエスケープしなくていい文字はどれか?

投稿2022/04/11 15:51

jimbe

総合スコア13170

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

curveworks

2022/04/25 04:18

ご回答ありがとうございました。 自分の認識として、application/x-www/urlencodedでリクエストを送信する場合、=も&も含めてすべてエンコードする必要がある前提の頭になっていたことによる質問でした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問