29

我需要解码包含查询字符串的 URI;预期的输入/输出行为类似于以下内容:

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

我试过使用java.net.URI,但它似乎解码了查询字符串,所以在上面的例子中,我留下了“alias=pos&FirstName=Foo+A&B=C&LastName=Bar”,所以“& " 是查询分隔符或查询组件中的字符。

编辑:我刚刚尝试了 URI.getRawQuery()并且它没有进行编码,所以我可以用 a 拆分查询字符串&,但是我该怎么办?Javascript 有decodeURIComponent,我似乎在 Java 中找不到对应的方法。

有什么建议么?我宁愿不使用任何新的库。

4

5 回答 5

67

采用

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

模拟decodeURIComponent. JavaURLDecoder将加号解码为空格,这不是您想要的,因此您需要替换语句。

警告:正如@xehpuk 指出的那样,如果原始(pre-x-www-form-urlencoded)包含该字符串,.replace("%2B", "+")最后损坏您的数据。

于 2011-08-03T13:12:50.070 回答
16

参见类URLDecoder

于 2010-04-13T18:58:56.577 回答
6
var reqParam =  URLDecoder.decode(reqParam, "UTF-8")
于 2016-12-14T17:15:10.327 回答
0

关于 + 号的问题:

我根据@janb 的回答制作了一个包装 URLDecoder 函数的辅助类

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

}
于 2016-04-01T12:19:54.420 回答
0
new java.net.URI(proxyRequestParam).getPath()

js encodeURIComponent编码的字符串应该只是一个路径,没有schema等。但是它仍然是 java.net.URI 的有效输入。所以 java.net.URI 将为我们做所有事情,然后它的路径就是我们想要的。

于 2020-05-11T02:59:27.257 回答