2009-03-11 30 views
7

Tôi có một Bản đồ với dữ liệu của tôi và muốn xây dựng một chuỗi truy vấn với nó, giống như tôi làm với http_build_query trên PHP. Tôi không chắc liệu mã này có phải là cách triển khai tốt nhất hay nếu tôi quên một điều gì đó?Có bất kỳ Java tương đương với hàm http_build_query của PHP không?

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

Mã của bạn có hoạt động không? Vấn đề ở đâu? Câu hỏi là gì? –

+0

Mã của tôi hoạt động. Câu hỏi của tôi là nếu có bất kỳ lớp hoặc phương pháp nào thực hiện điều này một cách tốt hơn. Tôi không muốn phát minh lại bánh xe nếu có điều gì đó sẵn sàng cho nó có thể có cách tiếp cận tốt hơn đối với vụ án hơn mã của tôi. – falmp

Trả lời

6

nhìn vào lớp QueryStringBuildertest class của nó:

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

Tôi chấp nhận câu trả lời này vì đó là chính xác những gì tôi đã hỏi. Tôi đang giữ phiên bản của riêng mình mặc dù tôi đã khá gần với nó. :) – falmp

+0

Trông đẹp, bạn nên xem xét đóng gói hoặc gửi nó như một thư viện. Một phân số nhỏ, tên là gây hiểu nhầm - nó không chỉ xây dựng một chuỗi truy vấn, nó còn bao gồm một đường dẫn. – pimlottc

+0

Đây là liên kết bị hỏng ngay bây giờ. – Flimm

0

Trông OK, với những hãy cẩn thận:

  • làm cho thông số một Map<String, String> chứ không phải đúc chìa khóa và giá trị cho String.
  • mã hóa được mã hóa cứng trông đáng ngờ. UTF-8 không phải là đã cho, nó phải khớp với mã hóa được xác định trong tiêu đề của yêu cầu HTTP. Vì vậy, các mã nên đảm bảo rằng họ làm - ít nhất là xác định nó như là một hằng số một nơi nào đó và tham khảo rằng cả hai ở đây và bất cứ nơi nào mã hóa yêu cầu được thiết lập.

Chỉnh sửa: Có vẻ như tôi đã sai về mã hóa; Các tham số HTTP GET không phụ thuộc vào tiêu đề mã hóa và không có mã hóa rõ ràng theo truyền thống. RFC 3988 dường như chỉ định UTF-8, nhưng điều đó nghe khá giòn với tôi, vì vậy trừ khi bạn kiểm soát chặt chẽ máy chủ và có thể đảm bảo rằng nó thực sự sử dụng UTF-8, tôi sẽ sử dụng các yêu cầu POST cho bất kỳ dữ liệu nào không nằm trong phạm vi ASCII 7bit.

+0

a) Đã sửa lỗi, cảm ơn. b) Có vẻ như bạn đã đúng, nhưng tôi đang sử dụng nhà vệ sinh.org gói để thực hiện một yêu cầu REST và nó không cho phép bạn xác định mã hóa của yêu cầu. Giả sử nó không chỉ định một, mặc định là gì? Phụ thuộc vào cấu hình máy chủ? – falmp

1

Bạn có thể muốn kiểm tra các tiêu đề yêu cầu "Chấp nhận" cho mã hóa được hỗ trợ bởi các khách hàng trước khi buộc UTF-8 (mặc dù nó có thể là sự lựa chọn tốt nhất).

2

Sức mạnh thực sự của hàm http_build_query PHP là khả năng lấy mảng kết hợp và dịch thành chuỗi URL. Các mã sau làm điều tương tự và nó cho phép params url được xây dựng như bản đồ đa cấp bao gồm lồng nhau Bản đồ và Bộ sưu tập.Với một số công việc nhiều hơn này hỗ trợ cho Array cũng có thể được thêm vào.

Phương pháp thử được hiển thị bên dưới.

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")); 

} 

} 

Để dễ dàng kiểm tra kết quả của bạn nối chuỗi kết quả bằng các chuỗi truy vấn của url thực trỏ đến PHP này. Ví dụ

 
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

Tôi nghĩ rằng đây sẽ là câu trả lời đúng. –

1

này nên là đơn giản nhất (và đáng tin cậy nhất) giải pháp:

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

dụ sử dụng:

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

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

Java không mã hóa các dấu hoa thị (+) trong khi PHP mã hóa nó %2A nên là sự khác biệt duy nhất.

Các vấn đề liên quan