2010-04-13 7 views
20

Ich muss einen URI dekodieren, der eine Abfragezeichenfolge enthält; erwartetes Ein-/Ausgabeverhalten ist so etwas wie die folgende:Entschlüsselungs-URI-Abfragezeichenfolge in Java

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

Ich habe versucht, java.net.URI verwenden, aber es scheint, den Query-String zu dekodieren so in dem obigen Beispiel I mit „alias = po & Vorname = links bin Foo + A & B = C & LastName = Balken "so gibt es Mehrdeutigkeit, ob ein" & "ein Abfragetrennzeichen ist oder ein Zeichen in einer Abfragekomponente ist.

Edit: Ich habe gerade versucht URI.getRawQuery() und es ist die Codierung nicht tun, so kann ich das Query-String mit einem & gespalten, aber dann, was soll ich tun? Javascript hat decodeURIComponent, ich kann nicht scheinen, die entsprechende Methode in Java zu finden.

Irgendwelche Vorschläge? Ich würde es vorziehen, keine neuen Bibliotheken zu verwenden.

+0

Da Sie nicht wollen, basierend hüllt Um neue Bibliotheken einzuführen, darf ich fragen, in welcher Umgebung Sie diese URIs erhalten? – stacker

Antwort

15

Siehe Klasse URLDecoder

+4

Es sollte beachtet werden, dass Sie den Abfrageteil identifizieren und die Parameter vor der Verwendung in Schlüssel/Wert-Paare aufteilen sollten, aber prozentcodierte Werte gemäß HTML in die angegebene Kodierung (siehe UTF-8) dekodieren Anwendung/x-www-form-urlencoded' spec. – McDowell

53

Verwenden

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

zu decodeURIComponent zu simulieren. Javas URLDecoder dekodiert das Pluszeichen in ein Leerzeichen, was nicht das ist, was Sie wollen, deshalb brauchen Sie die replace-Anweisungen.

Warnung: die .replace("%2B", "+") am Ende wird Ihre Daten zerstören wenn das Original (pre-x-www-form-urlencoded) diese Zeichenfolge enthalten, wie @xehpuk darauf hingewiesen.

+3

Dies sollte die akzeptierte Antwort sein. URIs behandeln das Symbol + wie es ist, während Leerzeichen in% 20 codiert sind. URLDecoder ist nicht kompatibel mit URI-codierten Strings, da es sowohl + als auch% 20 in ein Leerzeichen decodiert. – Kosta

+3

Was ist der Sinn des zweiten Ersatzes? Nach der Dekodierung wird es keine Instanzen von "% 2B" in der Zeichenfolge mehr geben, da sie alle durch "+" ersetzt wurden, so dass nichts für die Ersetzung vorhanden sein wird. –

+2

Der Punkt ist, dass Sie keine codierten Zeichen in einer decodierten Zeichenfolge möchten. Da Java das + -Zeichen nicht als JavaScript dekodiert, kodiere ich zuerst das + -Zeichen, so dass es nicht von Java berührt wird, und decade dann das% 2B in + -Zeichen. Um kurz zu sein: Wenn ich dies nicht tun würde die decodierte URL nicht die ursprünglichen + -Zeichen enthalten (da Java sie in der Dekodierungsphase verloren hätte). – janb

0

In Bezug auf die Ausgabe mit dem Pluszeichen:

ich eine Hilfsklasse gemacht, die die URLDecoder Funktion auf die Antwort von @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")