web-dev-qa-db-fra.com

Décodage de la chaîne de requête URI en Java

Je dois décoder un URI contenant une chaîne de requête. comportement attendu d'entrée/sortie est quelque chose comme ce qui suit:

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

J'ai essayé d'utiliser Java.net.URI , mais il semble décoder la chaîne de requête. Dans l'exemple ci-dessus, il me reste donc "alias = pos & FirstName = Foo + A & B = C & LastName = Bar", ce qui crée une ambiguïté. si "&" est un séparateur de requête ou un caractère dans un composant de requête.

Edit: Je viens d'essayer URI.getRawQuery () et il ne fait pas l'encodage, je peux donc scinder la chaîne de requête avec un &, mais que puis-je faire? Javascript a decodeURIComponent , je n'arrive pas à trouver la méthode correspondante en Java.

Aucune suggestion? Je préférerais ne pas utiliser de nouvelles bibliothèques.

21
Jason S

Voir classe URLDecoder

16
Maurice Perry

Utilisation 

URLDecoder.decode(proxyRequestParam.replace("+", "%2B"), "UTF-8")
          .replace("%2B", "+")

simuler decodeURIComponent. La variable URLDecoder de Java décode le signe plus en un espace, ce qui n'est pas ce que vous voulez, vous avez donc besoin des instructions de remplacement.

Attention: le .replace("%2B", "+") à la fin will corrompre vos données if l'original (pre-x-www-form-urlencoded) contenait cette chaîne, comme l'a souligné @xehpuk .

58
janb
var reqParam =  URLDecoder.decode(reqParam, "UTF-8")
4
Bhaskara Arani

En ce qui concerne le problème avec le signe +:

J'ai créé une classe d'assistance qui englobe la fonction URLDecoder en fonction de la réponse 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;
    }

}
0
IHeartAndroid