2010-04-13 26 views
20

我需要解碼包含查詢字符串的URI;預期輸入/輸出行爲是類似如下:在Java中解碼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嘗試過,但似乎這樣在上面的例子中我留下了「別名= POS &名字=到查詢字符串解碼Foo + A & B = C & LastName = Bar「因此,不管」&「是查詢分隔符還是查詢組件中的字符都不明確。

編輯:我只是想URI.getRawQuery(),並沒有做編碼,這樣我就可以用&分割查詢字符串,但後來我該怎麼辦? Javascript有decodeURIComponent,我似乎無法在Java中找到相應的方法。

有什麼建議嗎?我不想使用任何新的庫。

+0

的答案既然你不想URLDecoder功能的輔助類爲了引入新的庫,我可以問你在哪個環境中接收這些URI? – stacker 2010-04-13 19:39:16

回答

15

見類URLDecoder

+4

需要注意的是,在使用這個函數之前,您應該確定查詢部分並將參數拆分爲鍵/值對,但是它會根據HTML代碼將百分比編碼的值解碼爲給定的編碼(請參閱UTF-8) application/x-www-form-urlencoded' spec。 – McDowell 2010-04-13 22:29:25

53

使用

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

模擬decodeURIComponent。 Java的URLDecoder將加號解碼爲空格,這不是您想要的,因此您需要替換語句。

警告:.replace("%2B", "+")破壞你的數據如果原(前X WWW的形式,進行了urlencoded)含有該字符串,如@xehpuk指出。

+3

這應該是被接受的答案。 URI按原樣處理+符號,而空格則編碼爲%20。 URLDecoder與URI編碼的字符串不兼容,因爲它會將+和%20解碼爲一個空格。 – Kosta 2012-04-17 09:15:56

+3

第二次更換有什麼意義?解碼後,字符串中將不再有「%2B」的任何實例,因爲它們全部被替換爲「+」,所以替換無法匹配。 – 2012-08-16 19:45:05

+2

重點是你不想要解碼字符串中的編碼字符。由於Java不會像JavaScript那樣解碼+ -sign,所以我首先對+ -ign進行編碼,以便Java不會觸及它,然後將%2B解碼爲+ -sign。 簡而言之:如果我不這樣做,解碼後的URL將不包含原始的+符號(因爲Java在解碼階段會失去它們)。 – janb 2012-08-21 10:05:36

0

關於與+號問題:

我做了一個包裝基於@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; 
    } 

} 
1
var reqParam = URLDecoder.decode(reqParam, "UTF-8")