urldecoder - Decodificación de la cadena de consulta URI en Java
urlencoder encode utf-8 example java (4)
Necesito descifrar un URI que contiene una cadena de consulta; El comportamiento esperado de entrada / salida es algo como lo siguiente:
abstract class URIParser
{
/** example input:
* something?alias=pos&FirstName=Foo+A%26B%3DC&LastName=Bar */
URIParser(String input) { ... }
/** should return "something" for the example input */
public String getPath();
/** should return a map
* {alias: "pos", FirstName: "Foo+A&B=C", LastName: "Bar"} */
public Map<String,String> getQuery();
}
He intentado usar java.net.URI , pero parece que decodifica la cadena de consulta, así que en el ejemplo anterior me quedo con "alias = pos & FirstName = Foo + A & B = C & LastName = Bar", por lo que hay ambigüedad sobre si un "& "es un separador de consulta o es un carácter en un componente de consulta.
Edición: Acabo de probar URI.getRawQuery() y no hace la codificación, por lo que puedo dividir la cadena de consulta con un &
, pero ¿qué hago? Javascript tiene decodeURIComponent , parece que no puedo encontrar el método correspondiente en Java.
¿Alguna sugerencia? Preferiría no usar ninguna nueva biblioteca.
Respecto al tema con el signo +:
Hice una clase de ayuda que envuelve la función URLDecoder basada en la respuesta de @janb
import android.net.Uri;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class DateDecoder {
private static final String KEY_DATE = "datekey";
private static final SimpleDateFormat SIMPLE_DATE_FORMAT =
new SimpleDateFormat("yyyy-MM-dd''T''HH:mm:ssZZZZZ", Locale.US);
public static void main(String[] args) throws UnsupportedEncodingException {
try {
Uri uri = Uri.parse("http://asdf.com?something=12345&" +
KEY_DATE +"=2016-12-24T12:00:00+01:00");
System.out.println("parsed date: " + DateDecoder.createDate(uri)); // parsed date: Sat Dec 24 12:00:00 GMT+01:00 2016
} catch (Exception e) {
e.printStackTrace();
}
}
@Nullable
public static Date createDate(@Nullable Uri data) {
if (data != null) {
try {
String withPlus = decodeButKeepPlus(KEY_DATE, data.getEncodedQuery());
if (!TextUtils.isEmpty(withPlus)) {
return SIMPLE_DATE_FORMAT.parse(withPlus);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* copied from android.net.Uri.java
*/
@Nullable
public static String decodeButKeepPlus(String encodedKey, String completeEncodedQuery)
throws UnsupportedEncodingException {
final int length = completeEncodedQuery.length();
int start = 0;
do {
int nextAmpersand = completeEncodedQuery.indexOf(''&'', start);
int end = nextAmpersand != -1 ? nextAmpersand : length;
int separator = completeEncodedQuery.indexOf(''='', start);
if (separator > end || separator == -1) {
separator = end;
}
if (separator - start == encodedKey.length()
&& completeEncodedQuery.regionMatches(start, encodedKey, 0, encodedKey.length())) {
if (separator == end) {
return "";
} else {
String encodedValue = completeEncodedQuery.substring(separator + 1, end);
if (!TextUtils.isEmpty(encodedValue)) {
return URLDecoder.decode(encodedValue.replace("+", "%2B"), "UTF-8").replace("%2B", "+");
}
}
}
// Move start to end of name.
if (nextAmpersand != -1) {
start = nextAmpersand + 1;
} else {
break;
}
} while (true);
return null;
}
}
Utilizar
URLDecoder.decode(proxyRequestParam.replace("+", "%2B"), "UTF-8")
.replace("%2B", "+")
para simular decodeURIComponent
. El URLDecoder
de Java decodifica el signo más a un espacio, que no es lo que desea, por lo que necesita las declaraciones de reemplazo.
Advertencia: el
.replace("%2B", "+")
al final dañará sus datos si el original (pre-x-www-form-urlencoded) contenía esa cadena, como lo señaló @xehpuk.
Ver clase URLDecoder
var reqParam = URLDecoder.decode(reqParam, "UTF-8")