URL文字列からクエリストリングを取得するのに、どうしてよいかわからず、調べた結果をメモします。
参考サイト
実装結果
参考サイトに記載あるように以下の通り実装しました。
String url = "http://www.example.com/something.html?one=1&two=2&three=3&three=3a";
List<NameValuePair> params = URLEncodedUtils.parse(new URI(url), "UTF-8");
for (NameValuePair param : params) {
System.out.println(param.getName() + " : " + param.getValue());
}
NameValuePair#getName()でクエリストリングのkey値が
NameValuePair#getValue()でvalue値が取得可能です。
補足(逆パターン)
URLの組み立てには、 javax.ws.rs.core.UriBuilderを使用しました。 使用例は以下の通りです。 ※UriBuilder#queryParam()でクエリストリングを追加しています。
String urlParts = "1234567"
String embedUrl = "https://www.youtube.com/embed/" + urlParts;
String returnValue = UriBuilder.fromUri(embedUrl)
.queryParam("autohide", "2")
.queryParam("autoplay", "0")
.queryParam("cc_load_policy", "0")
.queryParam("controls", "1")
.queryParam("disablekb", "0")
.queryParam("enablejsapi", "0")
.queryParam("fs", "1")
.queryParam("iv_load_policy", "1")
.queryParam("loop", "0")
.queryParam("modestbranding", "0").toString();
感想
Android の Uri とか、Uri.Builder がいい感じに使える気がするので、
なんだか面倒だなという気になりました。
※もっといい方法があるのかもしれません。
クエリストリングのキー値に重複がある場合
気になり始めたため、以下のようなプログラムを作成して、
戻りを確認してみました。
-
NameValuePairGetQueryStringFromUrlExample.java
import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; import java.net.URI; import java.net.URISyntaxException; import java.util.List; /** * NameValuePairGetQueryStringFromUrlExample */ public class NameValuePairGetQueryStringFromUrlExample { public static void main(String... args) { // Use Guava String uri1 = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback"; List<NameValuePair> params1 = null; try { params1 = URLEncodedUtils.parse(new URI(uri1), "UTF-8"); } catch (URISyntaxException e) { e.printStackTrace(); } for (NameValuePair param : params1) { System.out.println(param.getName() + " : " + param.getValue()); } String uri2 = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&access_type=online&redirect_uri=http://localhost/Callback"; List<NameValuePair> params2 = null; try { params2 = URLEncodedUtils.parse(new URI(uri2), "UTF-8"); } catch (URISyntaxException e) { e.printStackTrace(); } for (NameValuePair param : params2) { System.out.println(param.getName() + " : " + param.getValue()); } } }
-
Output
access_type をキー値に持つ、NameValuePair
が2つ取得されました。
############ client_id : SS response_type : code scope : N_FULL access_type : offline redirect_uri : http://localhost/Callback ############ client_id : SS response_type : code scope : N_FULL access_type : offline access_type : online redirect_uri : http://localhost/Callback
その他の方法
上記以外の取得方法についての記載です。
Guavaを使う
- GuavaGetQueryStringFromUrlExample.java
import com.google.common.base.Splitter; import java.util.Map; import static java.lang.System.out; /** * GuavaGetQueryStringFromUrlExample */ public class GuavaGetQueryStringFromUrlExample { public static void main(String... args) { // Use Guava String uri1 = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback"; String query1 = uri1.split("\\?")[1]; final Map<String, String> useGuavaOutputMap1 = Splitter.on('&').trimResults().withKeyValueSeparator("=").split(query1); out.println("Use Guave START>>>"); out.println(useGuavaOutputMap1); out.println("<<<END"); String uri2 = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&access_type=online&redirect_uri=http://localhost/Callback"; String query2 = uri2.split("\\?")[1]; final Map<String, String> useGuavaOutputMap2 = Splitter.on('&').trimResults().withKeyValueSeparator("=").split(query2); out.println("Use Guave START>>>"); out.println(useGuavaOutputMap2); out.println("<<<END"); } }
- Output
キー値に重複があると、例外がスローされます。
Exception in thread "main" java.lang.IllegalArgumentException: Duplicate key [access_type] found. Use Guave START>>> {client_id=SS, response_type=code, scope=N_FULL, access_type=offline, redirect_uri=http://localhost/Callback} at com.google.common.base.Preconditions.checkArgument(Preconditions.java:148) <<<END at com.google.common.base.Splitter$MapSplitter.split(Splitter.java:506) at xyz.monotalk.google.webmaster.cli.getquerystringfromurl.GuavaGetQueryStringFromUrlExample.main(GuavaGetQueryStringFromUrlExample.java:25) Process finished with exit code 1
Java の標準API で処理する
-
JavaNativeGetQueryStringFromUrlExample.java クエリストリングとキー値を保持するMapを返します。
mport java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLDecoder; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import static java.lang.System.out; /** * JavaNativeGetQueryStringFromUrlExample */ public class JavaNativeGetQueryStringFromUrlExample { public static void main(String... args) { String uri1 = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback"; // Java Native final Map<String, List<String>> useJavaNativeOutputMap1 = splitQuery(uri1); out.println("Use Java Native START>>>"); out.println(useJavaNativeOutputMap1); out.println("<<<END"); String uri2 = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&access_type=online&redirect_uri=http://localhost/Callback"; // Java Native final Map<String, List<String>> useJavaNativeOutputMap2 = splitQuery(uri2); out.println("Use Java Native START>>>"); out.println(useJavaNativeOutputMap2); out.println("<<<END"); } public static Map<String, List<String>> splitQuery(String url) { URL urlObject = null; try { urlObject = new URL(url); } catch (MalformedURLException e) { throw new IllegalArgumentException(e); } final Map<String, List<String>> query_pairs = new LinkedHashMap<String, List<String>>(); final String[] pairs = urlObject.getQuery().split("&"); try { for (String pair : pairs) { final int idx = pair.indexOf("="); final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair; if (!query_pairs.containsKey(key)) { query_pairs.put(key, new LinkedList<String>()); } final String value = idx > 0 && pair.length() > idx + 1 ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8") : null; query_pairs.get(key).add(value); } } catch (UnsupportedEncodingException e) { throw new IllegalStateException(e); } return query_pairs; } }
-
Output キー値
access_type
に、2つにVlalue値が設定されました。
Use Java Native START>>> {client_id=[SS], response_type=[code], scope=[N_FULL], access_type=[offline], redirect_uri=[http://localhost/Callback]} <<<END Use Java Native START>>> {client_id=[SS], response_type=[code], scope=[N_FULL], access_type=[offline, online], redirect_uri=[http://localhost/Callback]} <<<END
POST送信などだと、キー値が複数の場合もざらにあるので、想定しとくべきパターンなのだと思います。
以上です。
コメント