2010-11-08 12 views
17

¿Alguien tiene, o conoce, una clase Java que puedo usar para manipular cadenas de consulta?Query String Manipulation en Java

Esencialmente, me gustaría una clase a la que simplemente pueda dar una cadena de consulta y luego eliminar, agregar y modificar cadenas de consulta KVP.

Gracias de antemano.

EDITAR

En respuesta a un comentario hecho a esta pregunta, la cadena de consulta se verá algo como esto;

N=123+456+112&Ntt=koala&D=abc 

Así que me gustaría pasar esta clase a la cadena de consulta y decir algo así como;

String[] N = queryStringClass.getParameter("N"); 

y luego tal vez

queryStringClass.setParameter("N", N); 

y tal vez queryStringClass.removeParameter("N");

O algo por el estilo.

+3

No ha proporcionado el contexto suficiente para que cualquiera pueda dar una respuesta. ¿Qué tipo de cadenas de consulta? Por favor reformula la pregunta. –

+1

http://stackoverflow.com/questions/1667278/parsing-query-strings-in-java –

Respuesta

16

algo como esto

public static Map<String, String> getQueryMap(String query) 
{ 
    String[] params = query.split("&"); 
    Map<String, String> map = new HashMap<String, String>(); 
    for (String param : params) 
    { 
     String name = param.split("=")[0]; 
     String value = param.split("=")[1]; 
     map.put(name, value); 
    } 
    return map; 
} 

para recorrer el mapa, simplemente:

String query = url.getQuery(); 
Map<String, String> map = getQueryMap(query); 
Set<String> keys = map.keySet(); 
for (String key : keys) 
{ 
    System.out.println("Name=" + key); 
    System.out.println("Value=" + map.get(key)); 
} 
+0

Me encantaría haber pre-construidos tenía algo, pero esto es genial. :) que – griegs

+1

gracias Sería más eficiente para almacenar 'param.split ("=")' en una variable y reutilizar el resultado en lugar de dividir el mismo parámetro dos veces. – LeastOne

+7

Esta solución no tiene en cuenta los caracteres que se han escapado. – raulk

0

Puede crear un método util y el uso de expresiones regulares para analizarlo. Un patrón como "[; &]" debería ser suficiente.

5

Si está utilizando J2EE, puede usar ServletRequest.getParameterValues().

De lo contrario, no creo que Java tenga clases comunes para el manejo de cadenas de consulta. Escribir el tuyo no debería ser demasiado difícil, aunque hay ciertos casos extremos complicados, como darse cuenta de que técnicamente la misma clave puede aparecer más de una vez en la cadena de consulta.

Una aplicación podría ser:

import java.util.*; 
import java.net.URLEncoder; 
import java.net.URLDecoder; 

public class QueryParams { 
private static class KVP { 
    final String key; 
    final String value; 
    KVP (String key, String value) { 
     this.key = key; 
     this.value = value; 
    } 
} 

List<KVP> query = new ArrayList<KVP>(); 

public QueryParams(String queryString) { 
    parse(queryString); 
} 

public QueryParams() { 
} 

public void addParam(String key, String value) { 
    if (key == null || value == null) 
     throw new NullPointerException("null parameter key or value"); 
    query.add(new KVP(key, value)); 
} 

private void parse(String queryString) { 
    for (String pair : queryString.split("&")) { 
     int eq = pair.indexOf("="); 
     if (eq < 0) { 
      // key with no value 
      addParam(URLDecoder.decode(pair), ""); 
     } else { 
      // key=value 
      String key = URLDecoder.decode(pair.substring(0, eq)); 
      String value = URLDecoder.decode(pair.substring(eq + 1)); 
      query.add(new KVP(key, value)); 
     } 
    } 
} 

public String toQueryString() { 
    StringBuilder sb = new StringBuilder(); 
    for (KVP kvp : query) { 
     if (sb.length() > 0) { 
      sb.append('&'); 
     } 
     sb.append(URLEncoder.encode(kvp.key)); 
     if (!kvp.value.equals("")) { 
      sb.append('='); 
      sb.append(URLEncoder.encode(kvp.value)); 
     } 
    } 
    return sb.toString(); 
} 

public String getParameter(String key) { 
    for (KVP kvp : query) { 
     if (kvp.key.equals(key)) { 
      return kvp.value; 
     } 
    } 
    return null; 
} 

public List<String> getParameterValues(String key) { 
    List<String> list = new LinkedList<String>(); 
    for (KVP kvp : query) { 
     if (kvp.key.equals(key)) { 
      list.add(kvp.value); 
     } 
    } 
    return list; 
} 

public static void main(String[] args) { 
    QueryParams qp = new QueryParams("k1=v1&k2&k3=v3&k1=v4&k1&k5=hello+%22world"); 
    System.out.println("getParameter:"); 
    String[] keys = new String[] { "k1", "k2", "k3", "k5" }; 
    for (String key : keys) { 
     System.out.println(key + ": " + qp.getParameter(key)); 
    } 
    System.out.println("getParameters(k1): " + qp.getParameterValues("k1")); 
} 
} 
+0

+1, gracias por esto. Ya implementado algo como esto. – griegs

+0

Cómo trabajar con "&" en medio de las cadenas de consulta? – Achimnol

+0

@Achimnol: ¿Cuál es el problema? & es una codificación XML, debe pasar a través de un parámetro de URL como% 26amp ;. Si desea seguir decodificando XML la cadena, puede usar otros métodos para eso. – Avi

12

También puede utilizar divisor de Google guayaba.

String queryString = "variableA=89&variableB=100"; 
Map<String,String> queryParameters = Splitter 
    .on("&") 
    .withKeyValueSeparator("=") 
    .split(queryString); 
System.out.println(queryParameters.get("variableA")); 

imprime

89 

Esto creo que es una alternativa muy legible a analizar por sí mismo.

Editar: Como @raulk señaló, esta solución no tiene en cuenta los caracteres que se han escapado. Sin embargo, esto puede no ser un problema porque antes de decodificar URL, se garantiza que la cadena de consulta no tendrá ningún carácter escapado que entre en conflicto con '=' y '&'. Puede usar esto para su ventaja de la siguiente manera.

decir que hay que decodificar la cadena de consulta siguiente:

a=%26%23%25!)%23(%40!&b=%23%24(%40)%24%40%40))%24%23%5E*%26 

que es URL codificada, a continuación, se le garantiza que el '&' y '=' se utilizan específicamente para la separación de pares y la clave de valor, respectivamente, momento en el que puede utilizar el adaptador de guayaba para obtener:

a = %26%23%25!)%23(%40! 
b = %23%24(%40)%24%40%40))%24%23%5E*%26 

Una vez que haya obtenido los pares de valores clave, entonces usted puede decodificar URL por separado.

a = &#%!)#(@! 
b = #$(@)[email protected]@))$#^*& 

Debe cubrir todos los casos.

+6

Este la solución no tiene en cuenta los caracteres escapados. – raulk

+0

Tendrás razón. –

+0

@raulk He agregado algunos pasos que podrían usarse incluso con caracteres escapados. ¡Gracias! –

1

Otra forma es utilizar Apache HTTP-componentes. Es un poco hacky, pero al menos se aprovechan todos los casos de esquina de análisis:

List<NameValuePair> params = 
    URLEncodedUtils.parse("http://example.com/?" + queryString, Charset.forName("UTF-8")); 

que usted va a dar una lista de objetos que deben ser NameValuePair fácil trabajar con él.

+0

Me pareció extraño que esto no haya sido propuesto ... esto es raro pero un buen uso de una biblioteca existente ... – AxelH