2009-03-11 26 views
7

Verilerimle bir Haritam var ve PHP'de http_build_query ile yaptığım gibi bir sorgu dizesi oluşturmak istiyorum. Bu kodun en iyi uygulaması mı, yoksa bir şey unutuyor muyum?PHP'nin http_build_query işlevinin herhangi bir Java karşılığı var mı?

public String toQueryString(Map<?, ?> data) throws UnsupportedEncodingException { 
    StringBuffer queryString = new StringBuffer(); 

    for (Entry<?, ?> pair : data.entrySet()) { 
     queryString.append (URLEncoder.encode ((String) pair.getKey(), "UTF-8") + "="); 
     queryString.append (URLEncoder.encode ((String) pair.getValue(), "UTF-8") + "&"); 
    } 

    if (queryString.length() > 0) { 
     queryString.deleteCharAt (queryString.length() - 1); 
    } 

    return queryString.toString(); 
} 
+0

Kodunuz çalışıyor mu? Sorun nerede? Soru nedir? –

+0

Kodum çalışıyor. Sorum şu, bunu daha iyi bir şekilde yapan herhangi bir sınıf veya yöntem var mıydı. Davayla ilgili daha iyi bir yaklaşım benimsemeye hazır bir şey varsa, tekerleği yeniden icat etmeyi sevmiyorum. – falmp

cevap

6

QueryStringBuilder sınıfa bakmak ve onun test class:

private String httpBuildQuery(Map<String, String> data) 
     throws UnsupportedEncodingException { 
    QueryStringBuilder builder = new QueryStringBuilder(); 
    for (Entry<String, String> pair : data.entrySet()) { 
     builder.addQueryParameter(pair.getKey(), pair.getValue()); 
    } 
    return builder.encode("UTF-8"); 
} 
+0

Bu cevabı kabul ediyorum çünkü tam olarak istediğim buydu. Ben kendi versiyonumuzu koruyorum, çünkü ona oldukça yakındım. :) – falmp

+0

Güzel görünüyor, paketlemeyi ya da bir kütüphane olarak göndermeyi düşünmelisin. Bir küçük kelime oyunu, yanıltıcıdır - sadece bir sorgu dizesi oluşturmak değil, aynı zamanda bir yol içerir. – pimlottc

+0

Bu şimdi kırık bir bağlantıdır. – Flimm

0

bu uyarılar ile, iyi görünüyor:

  • String anahtar ve değer döküm yerine parametre bir Map<String, String> olun.
  • Sabit kodlanmış kodlama şüpheli görünüyor. UTF-8 verilen değil, HTTP isteğinin başlığında tanımlanan kodlamayla eşleşmesi gerekiyor. Bu nedenle, kodun en azından bir yerde sabit olarak tanımlanmasını ve hem burada hem de istek kodlamasının ayarlandığını belirtmelidir.

Düzeltme: Kodlama konusunda yanılmışım gibi görünüyor; HTTP GET parametreleri bir kodlama başlığına tabi değildir ve geleneksel olarak iyi tanımlanmış bir kodlamaya sahip değildir. RFC 3988, UTF-8'i destekliyor gibi görünüyor, ancak bu bana oldukça kırılgan geliyor, bu nedenle sunucu üzerinde sıkı bir kontrole sahip olmadığınız ve gerçekten de UTF-8'i kullandığından emin olamadığınız sürece, herhangi bir veri için POST isteklerini kullanıyorum 7bit ASCII aralığında değil.

+0

a) Sabit, teşekkürler. b) Haklısınız, ama ben restlet kullanıyorum.Paketleri bir REST isteği yapmak ve isteğin kodlamasını tanımlamanıza izin vermez. Bir tane belirtmediğini varsayalım, varsayılan ne olurdu? Sunucu yapılandırmasına bağlı mı? – falmp

1

Muhtemelen muhtemelen olsa bile (UTF-8 zorlamadan önce istemci tarafından desteklenen kodlamaların için "Kabul" istek başlığını kontrol isterdim en iyi seçim).

2

PHP http_build_query işlevinin gerçek gücü, ilişkisel diziyi alma ve URL dizesine çevirme yeteneğidir. Aşağıdaki kod benzer bir şey yapar ve iç içe geçmiş Harita ve Koleksiyonlar içeren çok seviyeli Harita olarak url parametrelerinin oluşturulmasını sağlar. Daha fazla çalışarak Array için bir destek de eklenebilir.

Test yöntemleri aşağıda gösterilmiştir. sonuçlarınızın kolay test için

import java.io.UnsupportedEncodingException; 
import java.net.URLEncoder; 
import java.util.*; 

/** 
* Class: URLBuilder 
* User: Gilad Tiram 
* Date: 6/12/13 
* Time: 4:02 PM 
* <p/> 
* <p/> 
* Utility that helps to build URL String 
*/ 
public class URLBuilder { 


/** 
* Build URL string from Map of params. Nested Map and Collection is also supported 
* 
* @param params Map of params for constructing the URL Query String 
* @param encoding encoding type. If not set the "UTF-8" is selected by default 
* @return String of type key=value&...key=value 
* @throws java.io.UnsupportedEncodingException 
*   if encoding isnot supported 
*/ 
public static String httpBuildQuery(Map<String, Object> params, String encoding) { 
    if (isEmpty(encoding)) { 
     encoding = "UTF-8"; 
    } 
    StringBuilder sb = new StringBuilder(); 
    for (Map.Entry<String, Object> entry : params.entrySet()) { 
     if (sb.length() > 0) { 
      sb.append('&'); 
     } 

     String name = entry.getKey(); 
     Object value = entry.getValue(); 


     if (value instanceof Map) { 
      List<String> baseParam = new ArrayList<String>(); 
      baseParam.add(name); 
      String str = buildUrlFromMap(baseParam, (Map) value, encoding); 
      sb.append(str); 

     } else if (value instanceof Collection) { 
      List<String> baseParam = new ArrayList<String>(); 
      baseParam.add(name); 
      String str = buildUrlFromCollection(baseParam, (Collection) value, encoding); 
      sb.append(str); 

     } else { 
      sb.append(encodeParam(name)); 
      sb.append("="); 
      sb.append(encodeParam(value)); 
     } 


    } 
    return sb.toString(); 
} 

private static String buildUrlFromMap(List<String> baseParam, Map<Object, Object> map, String encoding) { 
    StringBuilder sb = new StringBuilder(); 
    String token; 

    //Build string of first level - related with params of provided Map 
    for (Map.Entry<Object, Object> entry : map.entrySet()) { 

     if (sb.length() > 0) { 
      sb.append('&'); 
     } 

     String name = String.valueOf(entry.getKey()); 
     Object value = entry.getValue(); 
     if (value instanceof Map) { 
      List<String> baseParam2 = new ArrayList<String>(baseParam); 
      baseParam2.add(name); 
      String str = buildUrlFromMap(baseParam2, (Map) value, encoding); 
      sb.append(str); 

     } else if (value instanceof List) { 
      List<String> baseParam2 = new ArrayList<String>(baseParam); 
      baseParam2.add(name); 
      String str = buildUrlFromCollection(baseParam2, (List) value, encoding); 
      sb.append(str); 
     } else { 
      token = getBaseParamString(baseParam) + "[" + name + "]=" + encodeParam(value); 
      sb.append(token); 
     } 
    } 

    return sb.toString(); 
} 

private static String buildUrlFromCollection(List<String> baseParam, Collection coll, String encoding) { 
    StringBuilder sb = new StringBuilder(); 
    String token; 
    if (!(coll instanceof List)) { 
     coll = new ArrayList(coll); 
    } 
    List arrColl = (List) coll; 

    //Build string of first level - related with params of provided Map 
    for (int i = 0; i < arrColl.size(); i++) { 

     if (sb.length() > 0) { 
      sb.append('&'); 
     } 

     Object value = (Object) arrColl.get(i); 
     if (value instanceof Map) { 
      List<String> baseParam2 = new ArrayList<String>(baseParam); 
      baseParam2.add(String.valueOf(i)); 
      String str = buildUrlFromMap(baseParam2, (Map) value, encoding); 
      sb.append(str); 

     } else if (value instanceof List) { 
      List<String> baseParam2 = new ArrayList<String>(baseParam); 
      baseParam2.add(String.valueOf(i)); 
      String str = buildUrlFromCollection(baseParam2, (List) value, encoding); 
      sb.append(str); 
     } else { 
      token = getBaseParamString(baseParam) + "[" + i + "]=" + encodeParam(value); 
      sb.append(token); 
     } 
    } 

    return sb.toString(); 
} 


private static String getBaseParamString(List<String> baseParam) { 
    StringBuilder sb = new StringBuilder(); 
    for (int i = 0; i < baseParam.size(); i++) { 
     String s = baseParam.get(i); 
     if (i == 0) { 
      sb.append(s); 
     } else { 
      sb.append("[" + s + "]"); 
     } 
    } 
    return sb.toString(); 
} 

/** 
* Check if String is either empty or null 
* 
* @param str string to check 
* @return true if string is empty. Else return false 
*/ 
public static boolean isEmpty(String str) { 
    return str == null || str.length() == 0; 
} 


private static String encodeParam(Object param) { 
    try { 
     return URLEncoder.encode(String.valueOf(param), "UTF-8"); 
    } catch (UnsupportedEncodingException e) { 
     return URLEncoder.encode(String.valueOf(param)); 
    } 
} 

/* ========================================================================= */ 
/* Test functions               */ 
/* ========================================================================= */ 


public static void main(String[] args) { 
    //basicTest(); 
    //testWithMap(); 
    //testWithList(); 
    //testWithNestedMap(); 
    //testWithNestedList(); 
    testCompound(); 
} 

private static void basicTest() { 
    Map<String, Object> params = new LinkedHashMap<String, Object>(); 
    params.put("a", "1"); 
    params.put("b", "2"); 
    params.put("c", "3"); 

    System.out.println(httpBuildQuery(params, "UTF-8")); 
} 

private static void testWithMap() { 
    Map<String, Object> params = new LinkedHashMap<String, Object>(); 
    params.put("a", "1"); 
    params.put("b", "2"); 

    Map<String, Object> cParams = new LinkedHashMap<String, Object>(); 
    cParams.put("c1", "c1val"); 
    cParams.put("c2", "c2val"); 
    params.put("c", cParams); 

    System.out.println(httpBuildQuery(params, "UTF-8")); 
} 

private static void testWithNestedMap() { 
    Map<String, Object> params = new LinkedHashMap<String, Object>(); 
    params.put("a", "1"); 
    params.put("b", "2"); 

    Map<String, Object> cParamsLevel1 = new LinkedHashMap<String, Object>(); 
    cParamsLevel1.put("cL1-1", "cLevel1-1val"); 
    cParamsLevel1.put("cL1-2", "cLevel1-2val"); 

    Map<String, Object> cParamsLevel2 = new LinkedHashMap<String, Object>(); 
    cParamsLevel2.put("cL2-1", "cLevel2-1val"); 
    cParamsLevel2.put("cL2-2", "cLevel2-2val"); 
    cParamsLevel1.put("cL1-3", cParamsLevel2); 

    params.put("c", cParamsLevel1); 

    System.out.println(httpBuildQuery(params, "UTF-8")); 
} 


private static void testWithList() { 
    Map<String, Object> params = new LinkedHashMap<String, Object>(); 
    params.put("a", "1"); 
    params.put("b", "2"); 

    List<Object> cParams = new ArrayList<Object>(); 
    cParams.add("c1val"); 
    cParams.add("c2val"); 
    params.put("c", cParams); 

    System.out.println(httpBuildQuery(params, "UTF-8")); 
} 


private static void testWithNestedList() { 
    Map<String, Object> params = new LinkedHashMap<String, Object>(); 
    params.put("a", "1"); 
    params.put("b", "2"); 

    List<Object> cParamsLevel1 = new ArrayList<Object>(); 
    cParamsLevel1.add("cL1-val1"); 
    cParamsLevel1.add("cL12-val2"); 

    List<Object> cParamsLevel2 = new ArrayList<Object>(); 
    cParamsLevel2.add("cL2-val1"); 
    cParamsLevel2.add("cL2-val2"); 
    cParamsLevel1.add(cParamsLevel2); 

    params.put("c", cParamsLevel1); 

    System.out.println(httpBuildQuery(params, "UTF-8")); 
} 


private static void testCompound() { 

    Map<String, Object> params = new LinkedHashMap<String, Object>(); 

    //flat 
    params.put("a", "1"); 
    params.put("b", "2"); 

    //Map level 1 
    Map<String, Object> cParamsLevel1 = new LinkedHashMap<String, Object>(); 
    cParamsLevel1.put("cL1-1", "cLevel1-1val"); 
    cParamsLevel1.put("cL1-2", "cLevel1-2val"); 

    //Map level 2 
    Map<String, Object> cParamsLevel2 = new LinkedHashMap<String, Object>(); 
    cParamsLevel2.put("cL2-1", "cLevel2-1val"); 
    cParamsLevel2.put("cL2-2", "cLevel2-2val"); 
    cParamsLevel1.put("cL1-3", cParamsLevel2); 

    params.put("c", cParamsLevel1); 

    //List level 1 
    List<Object> dParamsLevel1 = new ArrayList<Object>(); 
    dParamsLevel1.add("dL1-val1"); 
    dParamsLevel1.add("dL12-val2"); 

    //List level 2 
    List<Object> dParamsLevel2 = new ArrayList<Object>(); 
    dParamsLevel2.add("dL2-val1"); 
    dParamsLevel2.add("dL2-val2"); 
    dParamsLevel1.add(dParamsLevel2); 

    params.put("d", dParamsLevel1); 

    System.out.println(httpBuildQuery(params, "UTF-8")); 

} 

} 

bu PHP işaret gerçek url sorgu String olarak testlerle sonuçlandı dizesi ekleyin.

protected static String httpBuildQuery(List<? extends NameValuePair> parameters, String encoding) { 
    return URLEncodedUtils.format(parameters, encoding).replace("*", "%2A"); 
} 

Örnek kullanım: Örnek

 
http://localhost/test.php?a=1&b=2&c[cL1-1]=cLevel1-1val&c[cL1-2]=cLevel1-2val&c[cL1-3][cL2-1]=cLevel2-1val&c[cL1-3][cL2-2]=cLevel2-2val&d[0]=dL1-val1&d[1]=dL12-val2&d[2][0]=dL2-val1&d[2][1]=dL2-val2 
<?php 
var_dump($_REQUEST); 
?> 
+0

Bence bu doğru cevap olmalı. –

1

Bu en kolay (ve en güvenilir) çözeltisi olmalıdır

List<NameValuePair> params = new ArrayList<NameValuePair>; 
params.add(new BasicNameValuePair("key", "value")); 

String queryString = httpBuildQuery(myParamList, "UTF-8"); 

Java PHP ise yıldız (+) kodlayan değil Bunu kodlamak tek fark %2A olmalıdır.

İlgili konular