Mam taki identyfikator URI:
https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback
Potrzebuję kolekcji z parsowanymi elementami:
NAME VALUE
------------------------
client_id SS
response_type code
scope N_FULL
access_type offline
redirect_uri http://localhost/Callback
Aby być dokładnym, potrzebuję odpowiednika Java dla metody C # / .NET HttpUtility.ParseQueryString .
Proszę o radę w tej sprawie.
Dzięki.
java
parsing
uri
namevaluecollection
Siergiej Szafiew
źródło
źródło
java.net.URI
/java.net.URL
?Odpowiedzi:
Jeśli szukasz sposobu na osiągnięcie tego celu bez korzystania z zewnętrznej biblioteki, pomoże ci następujący kod.
Możesz uzyskać dostęp do zwróconej mapy za
<map>.get("client_id")
pomocą adresu URL podanego w pytaniu, który zwróci „SS”.Dodano UPDATE -dekodowanie adresu URL
AKTUALIZACJA Ponieważ ta odpowiedź jest nadal dość popularna, stworzyłem ulepszoną wersję powyższej metody, która obsługuje wiele parametrów z tym samym kluczem i parametry bez wartości.
ZAKTUALIZUJ wersję Java8
Uruchomienie powyższej metody z adresem URL
https://stackoverflow.com?param1=value1¶m2=¶m3=value3¶m3
zwraca tę mapę:
źródło
org.apache.http.client.utils.URLEncodedUtils
jest dobrze znaną biblioteką, która może to dla Ciebie zrobić
Wyjścia
źródło
List<NameValuePair>
żeMap<String,String>
Java nie ma dostępu do nawiasów klamrowych, jest trywialne. Wyglądałoby to tak:map.get("one")
jeśli nie wiesz, jak to zrobić, powinno to być inne pytanie (ale najpierw spróbuj sam) . Wolimy ograniczyć pytania tutaj, w SOSystem.out.println(URLEncodedUtils.parse(new URI("http://example.com/?foo=bar&foo=baz"), "UTF-8"));
wypisze [foo = bar, foo = baz] .URLEncodedUtils and
NameValuePair` nie są już dostępne (chyba że dodasz zależność do starszej biblioteki Apache, jak opisano tutaj ).Jeśli używasz Spring Framework:
Dostaniesz:
źródło
UriComponentsBuilder.fromHttpUrl(url)
użyj Google Guava i zrób to w 2 liniach:
co daje ci
źródło
uri
, powinieneś użyć,new java.net.URL(uri).getQuery()
ponieważ to kupuje bezpłatną weryfikację wejścia na adres URL.splitter.split()
wyrzuci je,IllegalArgumentException
jeśli w ciągu zapytania znajduje się duplikat klucza. Zobacz stackoverflow.com/questions/1746507/…Najkrótszy sposób, jaki znalazłem, to ten:
AKTUALIZACJA:
UriComponentsBuilder
pochodzi z wiosny. Tutaj link .źródło
Dla Androida, jeśli używasz OkHttp w swoim projekcie. Możesz to zobaczyć. To proste i pomocne.
źródło
Instrukcja Java 8 one
Biorąc pod uwagę adres URL do analizy:
To rozwiązanie zbiera listę par:
To rozwiązanie natomiast zbiera mapę (biorąc pod uwagę, że w adresie URL może znajdować się więcej parametrów o tej samej nazwie, ale o różnych wartościach).
Oba rozwiązania muszą korzystać z funkcji narzędziowej, aby poprawnie dekodować parametry.
źródło
Jeśli używasz serwletu, spróbuj, spróbuj
źródło
HttpServletRequest
i działaMockHttpServletRequest
również z testami jednostkowymi Mock MVC.Jeśli używasz Java 8 i chcesz napisać kilka metod wielokrotnego użytku, możesz to zrobić w jednym wierszu.
Ale to dość brutalna linia.
źródło
Na Androida jest klasa Uri w pakiecie android.net . Pamiętaj, że Uri jest częścią android.net , podczas gdy URI jest częścią java.net .
Klasa Uri ma wiele funkcji do wydobywania par klucz-wartość z zapytania.
Następująca funkcja zwraca pary klucz-wartość w postaci HashMap.
W Javie:
W Kotlinie:
źródło
Korzystając z wyżej wymienionych komentarzy i rozwiązań, przechowuję wszystkie parametry zapytania za pomocą Map <String, Object>, gdzie Objects może być ciągiem znaków lub Set <String>. Rozwiązanie podano poniżej. Zaleca się użycie pewnego rodzaju walidatora adresu URL w celu sprawdzenia poprawności adresu URL, a następnie wywołania metody convertQueryStringToMap.
źródło
Wypróbowałem wersję Kotlin, widząc, jak to jest najlepszy wynik w Google.
I metody rozszerzenia
źródło
Gotowe do użycia rozwiązanie do dekodowania części zapytania URI (w tym dekodowania i wartości wielu parametrów)
Komentarze
Nie byłem zadowolony z kodu dostarczonego przez @ Pr0gr4mm3r w https://stackoverflow.com/a/13592567/1211082 . Rozwiązanie oparte na Streamie nie wykonuje URLDecoding, zmienna wersja niezgrabna.
W ten sposób opracowałem rozwiązanie, które
Map<String, List<Optional<String>>>
Optional.empty()
zamiastnull
)URLdecode
UnsupportedEncodingException
w wyjątek czasu wykonywania,RuntimeUnsupportedEncodingException
który umożliwia współdziałanie ze strumieniem. (Zawijanie zwykłej funkcji w funkcje zgłaszające sprawdzone wyjątki jest uciążliwe. A ScalaTry
nie jest dostępna w domyślnym języku Java).Kod Java
Kod Scala
... i ze względu na kompletność nie mogę się oprzeć dostarczeniu rozwiązania w Scali, które dominuje zwięzłość i piękno
źródło
Tylko aktualizacja wersji Java 8
Metody mapowania i toList () muszą być używane z modułami zbierającymi, których nie wymieniono w górnej odpowiedzi. W przeciwnym razie spowodowałoby to błąd kompilacji w IDE
źródło
splitQueryParameters()
metodę? A co z tym**Collectors**
?Odpowiedź Kotlina z początkowym odniesieniem od https://stackoverflow.com/a/51024552/3286489 , ale z ulepszoną wersją poprzez uporządkowanie kodów i udostępnienie 2 wersji oraz użycie niezmiennych operacji zbierania
Użyj,
java.net.URI
aby wyodrębnić zapytanie. Następnie użyj poniższych funkcji rozszerzeniapage2&page3
Otrzymasz{page=3}
, użyj poniższej funkcji rozszerzeniapage2&page3
otrzymasz{page=[2, 3]}
Sposób użycia go jak poniżej
źródło
Netty zapewnia również ładny parser ciągów zapytań o nazwie
QueryStringDecoder
. W jednym wierszu kodu może przeanalizować adres URL w pytaniu. Lubię, ponieważ nie wymaga łapania ani rzucaniajava.net.MalformedURLException
.W jednej linii:
Zobacz javadocs tutaj: https://netty.io/4.1/api/io/netty/handler/codec/http/QueryStringDecoder.html
Oto krótki, samodzielny, poprawny przykład:
który generuje
źródło
Odpowiadając tutaj, ponieważ jest to popularny wątek. To czyste rozwiązanie w Kotlinie, które korzysta z zalecanego
UrlQuerySanitizer
interfejsu API. Zobacz oficjalną dokumentację . Dodałem konstruktor ciągów, aby połączyć i wyświetlić parametry.źródło
Oto moje rozwiązanie z redukcją i opcjonalne :
Optional<SimpleImmutableEntry<String, String>>
ignorować śmieci późniejJeśli zapytasz, redukcja wymaga tego dziwnego sumatora w ostatnim parametrze, który jest używany tylko w równoległych strumieniach. Jego celem jest połączenie dwóch wyników pośrednich (tutaj HashMap).
źródło
Jeśli używasz Springa, dodaj argument typu
@RequestParam Map<String,String>
do metody kontrolera, a Spring zbuduje dla Ciebie mapę!źródło