usar thread progressbar personalizar bar java parsing uri namevaluecollection

personalizar - progressbar java thread



Analizar una cadena URI en la colección de nombre-valor (14)

Tengo el URI de esta manera:

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

Necesito una colección con elementos analizados:

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

Para ser exactos, necesito un equivalente de Java para C # HttpUtility.ParseQueryString Method. Por favor, dame un consejo sobre esto. Gracias.


org.apache.http.client.utils.URLEncodedUtils

Es una biblioteca muy conocida que puede hacerlo por ti.

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()); }

Salidas

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


Java 8 una declaración

Dada la URL a analizar:

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");

Esta solución recoge una lista de pares:

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

Esta solución, por otro lado, recopila un mapa (dado que en una url puede haber más parámetros con el mismo nombre pero diferentes valores).

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

Ambas soluciones deben usar una función de utilidad para decodificar adecuadamente los parámetros.

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); } }


El camino más corto que he encontrado es este:

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

ACTUALIZACIÓN: UriComponentsBuilder viene de Spring. Aquí el enlace .


Para Android, si está utilizando OkHttp en su proyecto. Usted puede echar un vistazo a esto. Es simple y útil.

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


Probé una versión de Kotlin al ver que este es el mejor resultado en 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 }

Y los métodos de extensión.

fun List<String>.getOrEmpty(index: Int) : String { return getOrElse(index) {""} } fun String.decodeToUTF8(): String { URLDecoder.decode(this, "UTF-8") }


Respondiendo aquí porque este es un hilo popular. Esta es una solución limpia en Kotlin que utiliza la API UrlQuerySanitizer recomendada. Consulte la documentación oficial . He añadido un generador de cadenas para concatenar y mostrar los parámetros.

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") }


Si está buscando una manera de lograrlo sin usar una biblioteca externa, el siguiente código lo ayudará.

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; }

Puede acceder al Mapa devuelto usando <map>.get("client_id") , con la URL que figura en su pregunta, esto devolvería "SS".

ACTUALIZACIÓN de decodificación de URL añadida

ACTUALIZACIÓN Como esta respuesta sigue siendo bastante popular, hice una versión mejorada del método anterior, que maneja múltiples parámetros con la misma clave y parámetros sin valor también.

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; }

ACTUALIZAR la versión de Java8

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<>(key, value); }

Ejecutando el método anterior con la URL

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

devuelve este mapa:

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


Si está utilizando Java 8 y está dispuesto a escribir algunos métodos reutilizables, puede hacerlo en una línea.

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); } }

Pero esa es una línea bastante brutal.


Si está utilizando Spring Framework:

public static void main(String[] args) { String uri = "http://youhost.com/test?param1=abc&param2=def&param2=ghi"; 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)); }

Conseguirás:

param1: abc param2: def,ghi


Si está utilizando Spring, agregue un argumento de tipo @RequestParam Map<String,String> a su método de controlador, ¡y Spring construirá el mapa por usted!


Si está utilizando el servlet doGet intente esto

request.getParameterMap()

Devuelve un java.util.Map de los parámetros de esta solicitud.

Devuelve: un java.util.Map inmutable que contiene nombres de parámetros como claves y valores de parámetros como valores de mapa. Las claves en el mapa de parámetros son de tipo String. Los valores en el mapa de parámetros son de tipo String array.

( Documento de Java )


Solo una actualización a la versión de Java 8

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()))); }

Los métodos de mapeo y toList () se deben usar con Recopiladores que no se mencionó en la respuesta principal. De lo contrario lanzaría un error de compilación en IDE.


Usa google guava y hazlo en 2 líneas:

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); } }

lo que te da

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


Usando los comentarios y soluciones mencionados anteriormente, estoy almacenando todos los parámetros de consulta usando Map <String, Object> donde los objetos pueden ser string o Set <String>. La solución se da a continuación. Se recomienda usar algún tipo de validador de url para validar primero la url y luego llamar al método convertQueryStringToMap.

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; } }