Parse a URI String into Name-Value Collection

JavaParsingUriNamevaluecollection

Java Problem Overview


I've got the URI like this:

https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback

I need a collection with parsed elements:

NAME               VALUE
------------------------
client_id          SS
response_type      code
scope              N_FULL
access_type        offline
redirect_uri       http://localhost/Callback

To be exact, I need a Java equivalent for the C#/.NET HttpUtility.ParseQueryString method.

Java Solutions


Solution 1 - Java

If you are looking for a way to achieve it without using an external library, the following code will help you.

public static Map<String, String> splitQuery(URL url) throws UnsupportedEncodingException {
    Map<String, String> query_pairs = new LinkedHashMap<String, String>();
    String query = url.getQuery();
    String[] pairs = query.split("&");
    for (String pair : pairs) {
        int idx = pair.indexOf("=");
        query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
    }
    return query_pairs;
}

You can access the returned Map using <map>.get("client_id"), with the URL given in your question this would return "SS".

UPDATE URL-Decoding added

UPDATE As this answer is still quite popular, I made an improved version of the method above, which handles multiple parameters with the same key and parameters with no value as well.

public static Map<String, List<String>> splitQuery(URL url) throws UnsupportedEncodingException {
  final Map<String, List<String>> query_pairs = new LinkedHashMap<String, List<String>>();
  final String[] pairs = url.getQuery().split("&");
  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);
  }
  return query_pairs;
}

UPDATE Java8 version

public Map<String, List<String>> splitQuery(URL url) {
    if (Strings.isNullOrEmpty(url.getQuery())) {
        return Collections.emptyMap();
    }
    return Arrays.stream(url.getQuery().split("&"))
            .map(this::splitQueryParameter)
            .collect(Collectors.groupingBy(SimpleImmutableEntry::getKey, LinkedHashMap::new, mapping(Map.Entry::getValue, toList())));
}

public SimpleImmutableEntry<String, String> splitQueryParameter(String it) {
    final int idx = it.indexOf("=");
    final String key = idx > 0 ? it.substring(0, idx) : it;
    final String value = idx > 0 && it.length() > idx + 1 ? it.substring(idx + 1) : null;
    return new SimpleImmutableEntry<>(
        URLDecoder.decode(key, StandardCharsets.UTF_8),
        URLDecoder.decode(value, StandardCharsets.UTF_8)
    );
}

Running the above method with the URL

https://stackoverflow.com?param1=value1&param2=&param3=value3&param3

returns this Map:

{param1=["value1"], param2=[null], param3=["value3", null]}

Solution 2 - Java

org.apache.http.client.utils.URLEncodedUtils

is a well known library that can do it for you

import org.apache.hc.client5.http.utils.URLEncodedUtils

String url = "http://www.example.com/something.html?one=1&two=2&three=3&three=3a";

List<NameValuePair> params = URLEncodedUtils.parse(new URI(url), Charset.forName("UTF-8"));

for (NameValuePair param : params) {
  System.out.println(param.getName() + " : " + param.getValue());
}

Outputs

one : 1
two : 2
three : 3
three : 3a

Solution 3 - Java

If you are using Spring Framework:

public static void main(String[] args) {
    String uri = "http://my.test.com/test?param1=ab&param2=cd&param2=ef";
    MultiValueMap<String, String> parameters =
            UriComponentsBuilder.fromUriString(uri).build().getQueryParams();
    List<String> param1 = parameters.get("param1");
    List<String> param2 = parameters.get("param2");
    System.out.println("param1: " + param1.get(0));
    System.out.println("param2: " + param2.get(0) + "," + param2.get(1));
}

You will get:

param1: ab
param2: cd,ef

Solution 4 - Java

use google Guava and do it in 2 lines:

import java.util.Map;
import com.google.common.base.Splitter;

public class Parser {
    public static void main(String... args) {
        String uri = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback";
        String query = uri.split("\\?")[1];
        final Map<String, String> map = Splitter.on('&').trimResults().withKeyValueSeparator('=').split(query);
        System.out.println(map);
    }
}

which gives you

{client_id=SS, response_type=code, scope=N_FULL, access_type=offline, redirect_uri=http://localhost/Callback}

Solution 5 - Java

The shortest way I've found is this one:

MultiValueMap<String, String> queryParams =
            UriComponentsBuilder.fromUriString(url).build().getQueryParams();

UPDATE: UriComponentsBuilder comes from Spring. Here the link.

Solution 6 - Java

For Android, if you are using OkHttp in your project. You might get a look at this. It simple and helpful.

final HttpUrl url = HttpUrl.parse(query);
if (url != null) {
    final String target = url.queryParameter("target");
    final String id = url.queryParameter("id");
}

Solution 7 - Java

PLAIN Java 11

Given the URL to analyse:

URL url = new URL("https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback");

This solution collects a list of pairs:

List<Map.Entry<String, String>> list = Pattern.compile("&")
   .splitAsStream(url.getQuery())
   .map(s -> Arrays.copyOf(s.split("=", 2), 2))
   .map(o -> Map.entry(decode(o[0]), decode(o[1])))
   .collect(Collectors.toList());

This solution on the other hand collects a map (given that in a url there can be more parameters with same name but different values).

Map<String, List<String>> list = Pattern.compile("&")
   .splitAsStream(url.getQuery())
   .map(s -> Arrays.copyOf(s.split("=", 2), 2))
   .collect(groupingBy(s -> decode(s[0]), mapping(s -> decode(s[1]), toList())));

Both the solutions must use an utility function to properly decode the parameters.

private static String decode(final String encoded) {
    return Optional.ofNullable(encoded)
                   .map(e -> URLDecoder.decode(e, StandardCharsets.UTF_8))
                   .orElse(null);
}

Solution 8 - Java

If you are using servlet doGet try this

request.getParameterMap()

>Returns a java.util.Map of the parameters of this request.

>Returns: an immutable java.util.Map containing parameter names as keys and parameter values as map values. The keys in the parameter map are of type String. The values in the parameter map are of type String array.

>(Java doc)

Solution 9 - Java

On Android, there is a Uri class in package android.net . Note that Uri is part of android.net, whereas URI is part of java.net .

Uri class has many functions to extract key-value pairs from a query. enter image description here

Following function returns key-value pairs in the form of HashMap.

In Java:

Map<String, String> getQueryKeyValueMap(Uri uri){
    HashMap<String, String> keyValueMap = new HashMap();
    String key;
    String value;

    Set<String> keyNamesList = uri.getQueryParameterNames();
    Iterator iterator = keyNamesList.iterator();

    while (iterator.hasNext()){
        key = (String) iterator.next();
        value = uri.getQueryParameter(key);
        keyValueMap.put(key, value);
    }
    return keyValueMap;
}

In Kotlin:

fun getQueryKeyValueMap(uri: Uri): HashMap<String, String> {
        val keyValueMap = HashMap<String, String>()
        var key: String
        var value: String

        val keyNamesList = uri.queryParameterNames
        val iterator = keyNamesList.iterator()

        while (iterator.hasNext()) {
            key = iterator.next() as String
            value = uri.getQueryParameter(key) as String
            keyValueMap.put(key, value)
        }
        return keyValueMap
    }

Solution 10 - Java

If you're using Java 8 and you're willing to write a few reusable methods, you can do it in one line.

private Map<String, List<String>> parse(final String query) {
	return Arrays.asList(query.split("&")).stream().map(p -> p.split("=")).collect(Collectors.toMap(s -> decode(index(s, 0)), s -> Arrays.asList(decode(index(s, 1))), this::mergeLists));
}

private <T> List<T> mergeLists(final List<T> l1, final List<T> l2) {
	List<T> list = new ArrayList<>();
	list.addAll(l1);
	list.addAll(l2);
	return list;
}

private static <T> T index(final T[] array, final int index) {
	return index >= array.length ? null : array[index];
}

private static String decode(final String encoded) {
	try {
		return encoded == null ? null : URLDecoder.decode(encoded, "UTF-8");
	} catch(final UnsupportedEncodingException e) {
		throw new RuntimeException("Impossible: UTF-8 is a required encoding", e);
	}
}

But that's a pretty brutal line.

Solution 11 - Java

Netty also provides a nice query string parser called QueryStringDecoder. In one line of code, it can parse the URL in the question. I like because it doesn't require catching or throwing java.net.MalformedURLException.

In one line:

Map<String, List<String>> parameters = new QueryStringDecoder(url).parameters();

See javadocs here: https://netty.io/4.1/api/io/netty/handler/codec/http/QueryStringDecoder.html

Here is a short, self contained, correct example:

import io.netty.handler.codec.http.QueryStringDecoder;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;

public class UrlParse {

  public static void main(String... args) {
    String url = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback";
    QueryStringDecoder decoder = new QueryStringDecoder(url);
    Map<String, List<String>> parameters = decoder.parameters();
    print(parameters);
  }

  private static void print(final Map<String, List<String>> parameters) {
    System.out.println("NAME               VALUE");
    System.out.println("------------------------");
    parameters.forEach((key, values) ->
        values.forEach(val ->
            System.out.println(StringUtils.rightPad(key, 19) + val)));
  }
}

which generates

NAME               VALUE
------------------------
client_id          SS
response_type      code
scope              N_FULL
access_type        offline
redirect_uri       http://localhost/Callback

Solution 12 - Java

Using above mentioned comments and solutions, I am storing all the query parameters using Map<String, Object> where Objects either can be string or Set<String>. The solution is given below. It is recommended to use some kind of url validator to validate the url first and then call convertQueryStringToMap method.

private static final String DEFAULT_ENCODING_SCHEME = "UTF-8";

public static Map<String, Object> convertQueryStringToMap(String url) throws UnsupportedEncodingException, URISyntaxException {
    List<NameValuePair> params = URLEncodedUtils.parse(new URI(url), DEFAULT_ENCODING_SCHEME);
    Map<String, Object> queryStringMap = new HashMap<>();
    for(NameValuePair param : params){
        queryStringMap.put(param.getName(), handleMultiValuedQueryParam(queryStringMap, param.getName(), param.getValue()));
    }
    return queryStringMap;
}

private static Object handleMultiValuedQueryParam(Map responseMap, String key, String value) {
    if (!responseMap.containsKey(key)) {
        return value.contains(",") ? new HashSet<String>(Arrays.asList(value.split(","))) : value;
    } else {
        Set<String> queryValueSet = responseMap.get(key) instanceof Set ? (Set<String>) responseMap.get(key) : new HashSet<String>();
        if (value.contains(",")) {
            queryValueSet.addAll(Arrays.asList(value.split(",")));
        } else {
            queryValueSet.add(value);
        }
        return queryValueSet;
    }
}

Solution 13 - Java

I had a go at a Kotlin version seeing how this is the top result in Google.

@Throws(UnsupportedEncodingException::class)
fun splitQuery(url: URL): Map<String, List<String>> {

    val queryPairs = LinkedHashMap<String, ArrayList<String>>()

    url.query.split("&".toRegex())
            .dropLastWhile { it.isEmpty() }
            .map { it.split('=') }
            .map { it.getOrEmpty(0).decodeToUTF8() to it.getOrEmpty(1).decodeToUTF8() }
            .forEach { (key, value) ->

                if (!queryPairs.containsKey(key)) {
                    queryPairs[key] = arrayListOf(value)
                } else {

                    if(!queryPairs[key]!!.contains(value)) {
                        queryPairs[key]!!.add(value)
                    }
                }
            }

    return queryPairs
}

And the extension methods

fun List<String>.getOrEmpty(index: Int) : String {
    return getOrElse(index) {""}
}

fun String.decodeToUTF8(): String { 
    URLDecoder.decode(this, "UTF-8")
}

Solution 14 - Java

A ready-to-use solution for decoding of URI query part (incl. decoding and multi parameter values)

Comments

I wasn't happy with the code provided by @Pr0gr4mm3r in https://stackoverflow.com/a/13592567/1211082 . The Stream-based solution does not do URLDecoding, the mutable version clumpsy.

Thus I elaborated a solution that

  • Can decompose a URI query part into a Map<String, List<Optional<String>>>
  • Can handle multiple values for the same parameter name
  • Can represent parameters without a value properly (Optional.empty() instead of null)
  • Decodes parameter names and values correctly via URLdecode
  • Is based on Java 8 Streams
  • Is directly usable (see code including imports below)
  • Allows for proper error handling (here via turning a checked exception UnsupportedEncodingExceptioninto a runtime exception RuntimeUnsupportedEncodingException that allows interplay with stream. (Wrapping regular function into functions throwing checked exceptions is a pain. And Scala Try is not available in the Java language default.)

Java Code

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import static java.util.stream.Collectors.*;

public class URIParameterDecode {
    /**
     * Decode parameters in query part of a URI into a map from parameter name to its parameter values.
     * For parameters that occur multiple times each value is collected.
     * Proper decoding of the parameters is performed.
     * 
     * Example
     *   <pre>a=1&b=2&c=&a=4</pre>
     * is converted into
     *   <pre>{a=[Optional[1], Optional[4]], b=[Optional[2]], c=[Optional.empty]}</pre>
     * @param query the query part of an URI 
     * @return map of parameters names into a list of their values.
     *         
     */
    public static Map<String, List<Optional<String>>> splitQuery(String query) {
        if (query == null || query.isEmpty()) {
            return Collections.emptyMap();
        }

        return Arrays.stream(query.split("&"))
                    .map(p -> splitQueryParameter(p))
                    .collect(groupingBy(e -> e.get0(), // group by parameter name
                            mapping(e -> e.get1(), toList())));// keep parameter values and assemble into list
    }

    public static Pair<String, Optional<String>> splitQueryParameter(String parameter) {
        final String enc = "UTF-8";
        List<String> keyValue = Arrays.stream(parameter.split("="))
                .map(e -> {
                    try {
                        return URLDecoder.decode(e, enc);
                    } catch (UnsupportedEncodingException ex) {
                        throw new RuntimeUnsupportedEncodingException(ex);
                    }
                }).collect(toList());

        if (keyValue.size() == 2) {
            return new Pair(keyValue.get(0), Optional.of(keyValue.get(1)));
        } else {
            return new Pair(keyValue.get(0), Optional.empty());
        }
    }

    /** Runtime exception (instead of checked exception) to denote unsupported enconding */
    public static class RuntimeUnsupportedEncodingException extends RuntimeException {
        public RuntimeUnsupportedEncodingException(Throwable cause) {
            super(cause);
        }
    }

    /**
     * A simple pair of two elements
     * @param <U> first element
     * @param <V> second element
     */
    public static class Pair<U, V> {
        U a;
        V b;

        public Pair(U u, V v) {
            this.a = u;
            this.b = v;
        }

        public U get0() {
            return a;
        }

        public V get1() {
            return b;
        }
    }
}

Scala Code

... and for the sake of completeness I can not resist to provide the solution in Scala that dominates by brevity and beauty

import java.net.URLDecoder

object Decode {
  def main(args: Array[String]): Unit = {
    val input = "a=1&b=2&c=&a=4";
    println(separate(input))
  }

  def separate(input: String) : Map[String, List[Option[String]]] = {
    case class Parameter(key: String, value: Option[String])

    def separateParameter(parameter: String) : Parameter =
      parameter.split("=")
               .map(e => URLDecoder.decode(e, "UTF-8")) match {
      case Array(key, value) =>  Parameter(key, Some(value))
      case Array(key) => Parameter(key, None)
    }

    input.split("&").toList
      .map(p => separateParameter(p))
      .groupBy(p => p.key)
      .mapValues(vs => vs.map(p => p.value))
  }
}

Solution 15 - Java

Kotlin's Answer with initial reference from https://stackoverflow.com/a/51024552/3286489, but with improved version by tidying up codes and provides 2 versions of it, and use immutable collection operations

Use java.net.URI to extract the Query. Then use the below provided extension functions

  1. Assuming you only want the last value of query i.e. page2&page3 will get {page=3}, use the below extension function
    fun URI.getQueryMap(): Map<String, String> {
        if (query == null) return emptyMap()

        return query.split("&")
                .mapNotNull { element -> element.split("=")
                        .takeIf { it.size == 2 && it.none { it.isBlank() } } }
                .associateBy({ it[0].decodeUTF8() }, { it[1].decodeUTF8() })
    }

    private fun String.decodeUTF8() = URLDecoder.decode(this, "UTF-8") // decode page=%22ABC%22 to page="ABC"
  1. Assuming you want a list of all value for the query i.e. page2&page3 will get {page=[2, 3]}
    fun URI.getQueryMapList(): Map<String, List<String>> {
        if (query == null) return emptyMap()

        return query.split("&")
                .distinct()
                .mapNotNull { element -> element.split("=")
                        .takeIf { it.size == 2 && it.none { it.isBlank() } } }
                .groupBy({ it[0].decodeUTF8() }, { it[1].decodeUTF8() })
    }

    private fun String.decodeUTF8() = URLDecoder.decode(this, "UTF-8") // decode page=%22ABC%22 to page="ABC"

The way to use it as below

    val uri = URI("schema://host/path/?page=&page=2&page=2&page=3")
    println(uri.getQueryMapList()) // Result is {page=[2, 3]}
    println(uri.getQueryMap()) // Result is {page=3}

Solution 16 - Java

There are plenty of answers which work for your query as you've indicated when it has single parameter definitions. In some applications it may be useful to handle a few extra query parameter edge cases such as:

  • list of parameter values such as param1&param1=value&param1= meaning param1 is set to List.of("", "value", "")
  • invalid permutations such as querypath?&=&&=noparamname&.
  • use empty string not null in maps a= means "a" is List.of("") to match web servlet handling

This uses a Stream with filters and groupingBy to collect to Map<String, List<String>>:

public static Map<String, List<String>> getParameterValues(URL url) {
    return Arrays.stream(url.getQuery().split("&"))
            .map(s -> s.split("="))
            // filter out empty parameter names (as in Tomcat) "?&=&&=value&":
            .filter(arr -> arr.length > 0 && arr[0].length() > 0)
            .collect(Collectors.groupingBy(arr -> URLDecoder.decode(arr[0], StandardCharsets.UTF_8),
                     // drop this line for not-name definition order Map:
                     LinkedHashMap::new, 
                     Collectors.mapping(arr -> arr.length < 2 ? "" : URLDecoder.decode(arr[1], StandardCharsets.UTF_8), Collectors.toList())));
}

Solution 17 - Java

There a new version of Apache HTTP client - org.apache.httpcomponents.client5 - where URLEncodedUtils is now deprecated. URIBuilder should be used instead:

import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.net.URIBuilder;

private static Map<String, String> getQueryParameters(final String url) throws URISyntaxException {
    return new URIBuilder(new URI(url), StandardCharsets.UTF_8).getQueryParams()
                                                               .stream()
                                                               .collect(Collectors.toMap(NameValuePair::getName,
                                                                                         nameValuePair -> URLDecoder.decode(nameValuePair.getValue(), StandardCharsets.UTF_8)));
}

Solution 18 - Java

If you are using Spring, add an argument of type @RequestParam Map<String,String> to your controller method, and Spring will construct the map for you!

Solution 19 - Java

Just an update to the Java 8 version

public Map<String, List<String>> splitQuery(URL url) {
    if (Strings.isNullOrEmpty(url.getQuery())) {
        return Collections.emptyMap();
    }
    return Arrays.stream(url.getQuery().split("&"))
            .map(this::splitQueryParameter)
            .collect(Collectors.groupingBy(SimpleImmutableEntry::getKey, LinkedHashMap::new, **Collectors**.mapping(Map.Entry::getValue, **Collectors**.toList())));
}

mapping and toList() methods have to be used with Collectors which was not mentioned in the top answer. Otherwise it would throw compilation error in IDE

Solution 20 - Java

Answering here because this is a popular thread. This is a clean solution in Kotlin that uses the recommended UrlQuerySanitizer api. See the official documentation. I have added a string builder to concatenate and display the params.

    var myURL: String? = null

    if (intent.hasExtra("my_value")) {
        myURL = intent.extras.getString("my_value")
    } else {
        myURL = intent.dataString
    }

    val sanitizer = UrlQuerySanitizer(myURL)
    // We don't want to manually define every expected query *key*, so we set this to true
    sanitizer.allowUnregisteredParamaters = true
    val parameterNamesToValues: List<UrlQuerySanitizer.ParameterValuePair> = sanitizer.parameterList
    val parameterIterator: Iterator<UrlQuerySanitizer.ParameterValuePair> = parameterNamesToValues.iterator()

    // Helper simply so we can display all values on screen
    val stringBuilder = StringBuilder()

    while (parameterIterator.hasNext()) {
        val parameterValuePair: UrlQuerySanitizer.ParameterValuePair = parameterIterator.next()
        val parameterName: String = parameterValuePair.mParameter
        val parameterValue: String = parameterValuePair.mValue

        // Append string to display all key value pairs
        stringBuilder.append("Key: $parameterName\nValue: $parameterValue\n\n")
    }

    // Set a textView's text to display the string
    val paramListString = stringBuilder.toString()
    val textView: TextView = findViewById(R.id.activity_title) as TextView
    textView.text = "Paramlist is \n\n$paramListString"
    
    // to check if the url has specific keys
    if (sanitizer.hasParameter("type")) {
        val type = sanitizer.getValue("type")
        println("sanitizer has type param $type")
    }

Solution 21 - Java

Here is my solution with reduce and Optional:

private Optional<SimpleImmutableEntry<String, String>> splitKeyValue(String text) {
	String[] v = text.split("=");
	if (v.length == 1 || v.length == 2) {
		String key = URLDecoder.decode(v[0], StandardCharsets.UTF_8);
		String value = v.length == 2 ? URLDecoder.decode(v[1], StandardCharsets.UTF_8) : null;
		return Optional.of(new SimpleImmutableEntry<String, String>(key, value));
	} else
		return Optional.empty();
}

private HashMap<String, String> parseQuery(URI uri) {
	HashMap<String, String> params = Arrays.stream(uri.getQuery()
			.split("&"))
			.map(this::splitKeyValue)
			.filter(Optional::isPresent)
			.map(Optional::get)
			.reduce(
                // initial value
                new HashMap<String, String>(), 
                // accumulator
                (map, kv) -> {
				     map.put(kv.getKey(), kv.getValue()); 
				     return map;
			    }, 
                // combiner
                (a, b) -> {
				     a.putAll(b); 
				     return a;
			    });
	return params;
}
  • I ignore duplicate parameters (I take the last one).
  • I use Optional<SimpleImmutableEntry<String, String>> to ignore garbage later
  • The reduction start with an empty map, then populate it on each SimpleImmutableEntry

In case you ask, reduce requires this weird combiner in the last parameter, which is only used in parallel streams. Its goal is to merge two intermediate results (here HashMap).

Solution 22 - Java

If you happen to have cxf-core on the classpath and you know you have no repeated query params, you may want to use UrlUtils.parseQueryString.

Solution 23 - Java

The Eclipse Jersey REST framework supports this through UriComponent. Example:

import org.glassfish.jersey.uri.UriComponent;

String uri = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback";
MultivaluedMap<String, String> params = UriComponent.decodeQuery(URI.create(uri), true);
for (String key : params.keySet()) {
  System.out.println(key + ": " + params.getFirst(key));
}

Solution 24 - Java

If just want the parameters after the URL from a String. Then the following code will work. I am just assuming the simple Url. I mean no hard and fast checking and decoding. Like in one of my test case I got the Url and I know I just need the value of the paramaters. The url was simple. No encoding decoding needed.

String location = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback";
String location1 = "https://stackoverflow.com?param1=value1&param2=value2&param3=value3";
String location2 = "https://stackoverflow.com?param1=value1&param2=&param3=value3&param3";
	
	Map<String, String> paramsMap = Stream.of(location)
        .filter(l -> l.indexOf("?") != -1)
	    .map(l -> l.substring(l.indexOf("?") + 1, l.length()))
	    .flatMap(q -> Pattern.compile("&").splitAsStream(q))
	    .map(s -> s.split("="))
	    .filter(a -> a.length == 2)
	    .collect(Collectors.toMap(
	        a -> a[0], 
	    	a -> a[1],
	    	(existing, replacement) -> existing + ", " + replacement,
		    LinkedHashMap::new
	    ));
	
	System.out.println(paramsMap);

Thanks

Solution 25 - Java

That seems tidy to me the best way:

static Map<String, String> decomposeQueryString(String query, Charset charset) {
    return Arrays.stream(query.split("&"))
        .map(pair -> pair.split("=", 2))
        .collect(Collectors.toMap(
            pair -> URLDecoder.decode(pair[0], charset),
            pair -> pair.length > 1 ? URLDecoder.decode(pair[1], charset) : null)
        );
}

The prerequisite is that your query syntax does not allow repeated parameters.

Solution 26 - Java

org.keycloak.common.util.UriUtils

I had to parse URIs and Query Parameters in a Keycloak extension and found this utility classes very useful:

org.keycloak.common.util.UriUtils:
static MultivaluedHashMap<String,String> decodeQueryString(String queryString) 

There is also a useful method to delete one query parameter:

static String 	stripQueryParam(String url, String name)

And to parse the URL there is org.keycloak.common.util.KeycloakUriBuilder:

KeycloakUriBuilder 	uri(String uriTemplate)
String 	getQuery()

and lots of other goodies.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSergey ShafievView Question on Stackoverflow
Solution 1 - JavaPr0gr4mm3rView Answer on Stackoverflow
Solution 2 - JavaJuan MendesView Answer on Stackoverflow
Solution 3 - JavaxxgView Answer on Stackoverflow
Solution 4 - JavaAmin AbbaspourView Answer on Stackoverflow
Solution 5 - JavaDmitry SenkovichView Answer on Stackoverflow
Solution 6 - JavaTHANN PhearumView Answer on Stackoverflow
Solution 7 - JavafreedevView Answer on Stackoverflow
Solution 8 - JavaAnsar OzdenView Answer on Stackoverflow
Solution 9 - JavaRamakrishna JoshiView Answer on Stackoverflow
Solution 10 - JavaFuwjaxView Answer on Stackoverflow
Solution 11 - JavaKirbyView Answer on Stackoverflow
Solution 12 - JavaSUMITView Answer on Stackoverflow
Solution 13 - JavaGraham SmithView Answer on Stackoverflow
Solution 14 - JavaMartin SenneView Answer on Stackoverflow
Solution 15 - JavaElyeView Answer on Stackoverflow
Solution 16 - JavaDuncGView Answer on Stackoverflow
Solution 17 - JavaEnigoView Answer on Stackoverflow
Solution 18 - Javamancini0View Answer on Stackoverflow
Solution 19 - JavaAarish RameshView Answer on Stackoverflow
Solution 20 - JavajungledevView Answer on Stackoverflow
Solution 21 - JavaMike DudleyView Answer on Stackoverflow
Solution 22 - JavadschultenView Answer on Stackoverflow
Solution 23 - JavaJasper de VriesView Answer on Stackoverflow
Solution 24 - JavaBasitView Answer on Stackoverflow
Solution 25 - JavaMatthias RongeView Answer on Stackoverflow
Solution 26 - JavaFrerkView Answer on Stackoverflow