Java 如何将地图转换为url查询字符串?

Java 如何将地图转换为url查询字符串?,java,jakarta-ee,utilities,Java,Jakarta Ee,Utilities,您知道有任何实用程序类/库可以将地图转换为URL友好的查询字符串吗 例如: 我有一张地图: "param1"=12, "param2"="cat" 我想得到: param1=12&param2=cat 最终产量 relativeUrl+param1=12&param2=cat 这是我很快写下的东西;我相信这是可以改进的 import java.util.*; import java.io.UnsupportedEncodingException; import java.n

您知道有任何实用程序类/库可以将地图转换为URL友好的查询字符串吗

例如:

我有一张地图:

"param1"=12,
"param2"="cat"
我想得到:

param1=12&param2=cat
最终产量

relativeUrl+param1=12&param2=cat

这是我很快写下的东西;我相信这是可以改进的

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

public class MapQuery {
    static String urlEncodeUTF8(String s) {
        try {
            return URLEncoder.encode(s, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new UnsupportedOperationException(e);
        }
    }
    static String urlEncodeUTF8(Map<?,?> map) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<?,?> entry : map.entrySet()) {
            if (sb.length() > 0) {
                sb.append("&");
            }
            sb.append(String.format("%s=%s",
                urlEncodeUTF8(entry.getKey().toString()),
                urlEncodeUTF8(entry.getValue().toString())
            ));
        }
        return sb.toString();       
    }
    public static void main(String[] args) {
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("p1", 12);
        map.put("p2", "cat");
        map.put("p3", "a & b");         
        System.out.println(urlEncodeUTF8(map));
        // prints "p3=a+%26+b&p2=cat&p1=12"
    }
}
import java.util.*;
导入java.io.UnsupportedEncodingException;
导入java.net.urlcoder;
公共类映射查询{
静态字符串urlEncodeUTF8(字符串s){
试一试{
返回URLEncoder.encode(s,“UTF-8”);
}捕获(不支持的编码异常e){
抛出新的不支持操作异常(e);
}
}
静态字符串urlEncodeUTF8(映射){
StringBuilder sb=新的StringBuilder();
对于(Map.Entry:Map.entrySet()){
如果(sb.length()>0){
某人附加(“&”);
}
sb.append(字符串格式(“%s=%s”),
urlEncodeUTF8(entry.getKey().toString()),
urlEncodeUTF8(entry.getValue().toString())
));
}
使某人返回字符串();
}
公共静态void main(字符串[]args){
Map Map=newhashmap();
地图放置(“p1”,12);
地图放置(“p2”、“cat”);
地图放置(“p3”、“a&b”);
System.out.println(urlEncodeUTF8(map));
//打印“p3=a+%26+b&p2=cat&p1=12”
}
}

我看到的最健壮的一个是来自(HttpClient 4.0)的类

方法
URLEncodedUtils.format()
就是您所需要的

它不使用map,所以可以有重复的参数名,比如

  a=1&a=2&b=3

我并不建议使用这种参数名。

如果您确实想要构建一个完整的URI,请尝试从(HttpClient 4)开始


这实际上并没有回答这个问题,但它回答了我发现这个问题时遇到的问题。

另一个“一个类”/没有依赖性方法,处理单个/多个:

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class UrlQueryString {
  private static final String DEFAULT_ENCODING = "UTF-8";

  public static String buildQueryString(final LinkedHashMap<String, Object> map) {
    try {
      final Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator();
      final StringBuilder sb = new StringBuilder(map.size() * 8);
      while (it.hasNext()) {
        final Map.Entry<String, Object> entry = it.next();
        final String key = entry.getKey();
        if (key != null) {
          sb.append(URLEncoder.encode(key, DEFAULT_ENCODING));
          sb.append('=');
          final Object value = entry.getValue();
          final String valueAsString = value != null ? URLEncoder.encode(value.toString(), DEFAULT_ENCODING) : "";
          sb.append(valueAsString);
          if (it.hasNext()) {
            sb.append('&');
          }
        } else {
          // Do what you want...for example:
          assert false : String.format("Null key in query map: %s", map.entrySet());
        }
      }
      return sb.toString();
    } catch (final UnsupportedEncodingException e) {
      throw new UnsupportedOperationException(e);
    }
  }

  public static String buildQueryStringMulti(final LinkedHashMap<String, List<Object>> map) {
    try {
      final StringBuilder sb = new StringBuilder(map.size() * 8);
      for (final Iterator<Entry<String, List<Object>>> mapIterator = map.entrySet().iterator(); mapIterator.hasNext();) {
        final Entry<String, List<Object>> entry = mapIterator.next();
        final String key = entry.getKey();
        if (key != null) {
          final String keyEncoded = URLEncoder.encode(key, DEFAULT_ENCODING);
          final List<Object> values = entry.getValue();
          sb.append(keyEncoded);
          sb.append('=');
          if (values != null) {
            for (final Iterator<Object> listIt = values.iterator(); listIt.hasNext();) {
              final Object valueObject = listIt.next();
              sb.append(valueObject != null ? URLEncoder.encode(valueObject.toString(), DEFAULT_ENCODING) : "");
              if (listIt.hasNext()) {
                sb.append('&');
                sb.append(keyEncoded);
                sb.append('=');
              }
            }
          }
          if (mapIterator.hasNext()) {
            sb.append('&');
          }
        } else {
          // Do what you want...for example:
          assert false : String.format("Null key in query map: %s", map.entrySet());
        }
      }
      return sb.toString();
    } catch (final UnsupportedEncodingException e) {
      throw new UnsupportedOperationException(e);
    }
  }

  public static void main(final String[] args) {
    // Examples: could be turned into unit tests ...
    {
      final LinkedHashMap<String, Object> queryItems = new LinkedHashMap<String, Object>();
      queryItems.put("brand", "C&A");
      queryItems.put("count", null);
      queryItems.put("misc", 42);
      final String buildQueryString = buildQueryString(queryItems);
      System.out.println(buildQueryString);
    }
    {
      final LinkedHashMap<String, List<Object>> queryItems = new LinkedHashMap<String, List<Object>>();
      queryItems.put("usernames", new ArrayList<Object>(Arrays.asList(new String[] { "bob", "john" })));
      queryItems.put("nullValue", null);
      queryItems.put("misc", new ArrayList<Object>(Arrays.asList(new Integer[] { 1, 2, 3 })));
      final String buildQueryString = buildQueryStringMulti(queryItems);
      System.out.println(buildQueryString);
    }
  }
}
import java.io.UnsupportedEncodingException;
导入java.net.urlcoder;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.Iterator;
导入java.util.LinkedHashMap;
导入java.util.List;
导入java.util.Map;
导入java.util.Map.Entry;
公共类UrlQueryString{
私有静态最终字符串默认值_ENCODING=“UTF-8”;
公共静态字符串buildQueryString(最终LinkedHashMap映射){
试一试{
final Iterator it=map.entrySet().Iterator();
最终StringBuilder sb=新StringBuilder(map.size()*8);
while(it.hasNext()){
final Map.Entry=it.next();
最后一个字符串key=entry.getKey();
if(key!=null){
sb.append(URLEncoder.encode(键,默认_编码));
某人附加('=');
最终对象值=entry.getValue();
最终字符串值asString=value!=null?urlcoder.encode(value.toString(),默认编码):“”;
某人附加(价值字符串);
if(it.hasNext()){
某人附加('&');
}
}否则{
//做你想做的…例如:
assert false:String.format(“查询映射中的Null键:%s”,map.entrySet());
}
}
使某人返回字符串();
}捕获(最终未支持的编码异常e){
抛出新的不支持操作异常(e);
}
}
公共静态字符串buildQueryStringMulti(最终LinkedHashMap映射){
试一试{
最终StringBuilder sb=新StringBuilder(map.size()*8);
对于(最终迭代器mapIterator=map.entrySet().Iterator();mapIterator.hasNext();){
final Entry=mapIterator.next();
最后一个字符串key=entry.getKey();
if(key!=null){
最终字符串keyEncoded=urlcoder.encode(键,默认_编码);
最终列表值=entry.getValue();
某人附加(键编码);
某人附加('=');
如果(值!=null){
for(最终迭代器listIt=values.Iterator();listIt.hasNext();){
最终对象值Object=listIt.next();
sb.append(valueObject!=null?URLEncoder.encode(valueObject.toString(),默认编码):“”);
if(listIt.hasNext()){
某人附加('&');
某人附加(键编码);
某人附加('=');
}
}
}
if(mapIterator.hasNext()){
某人附加('&');
}
}否则{
//做你想做的…例如:
assert false:String.format(“查询映射中的Null键:%s”,map.entrySet());
}
}
使某人返回字符串();
}捕获(最终未支持的编码异常e){
抛出新的不支持操作异常(e);
}
}
公共静态void main(最终字符串[]args){
//示例:可以转换为单元测试。。。
{
final LinkedHashMap queryItems=新LinkedHashMap();
queryItems.put(“品牌”、“C&A”);
queryItems.put(“计数”,null);
查询项目投入(“杂项”,42);
最终字符串buildQueryString=buildQueryString(queryItems);
System.out.println(buildQueryString);
}
{
final LinkedHashMap queryItems=新LinkedHashMap();
put(“用户名”,新的ArrayList(Arrays.asList(新字符串[]{“bob”,“john”}));
queryItems.put(“null值”,null);
put(“misc”,新的ArrayList(Arrays.asList(新的整数[]{1,2,3}));
最终字符串buildQueryString=buildQueryStringMulti(queryItems);
System.out.println(buildQueryString);
}
}
}
需要时,您可以使用simple(在大多数情况下更易于编写)或multiple。请注意,这两种方法可以通过添加一个符号和。。。
如果您发现任何问题,请在评论中告诉我。

在Spring Util中,有更好的方法

import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
params.add("key", key);
params.add("storeId", storeId);
params.add("orderId", orderId);
UriComponents uriComponents =     UriComponentsBuilder.fromHttpUrl("http://spsenthil.com/order").queryParams(params).build();
ListenableFuture<ResponseEntity<String>> responseFuture =     restTemplate.getForEntity(uriComponents.toUriString(), String.class);
import org.springframework.util.LinkedMultiValueMap;
导入org.springframework.util.MultiValueMap;
导入org.springframework.util.concurrent.ListenableFuture;
导入org.springframework.web.util.Uri组件;
parameters.entrySet().stream()
    .map(p -> urlEncodeUTF8(p.getKey()) + "=" + urlEncodeUTF8(p.getValue()))
    .reduce((p1, p2) -> p1 + "&" + p2)
    .orElse("");
List<BasicNameValuePair> nameValuePairs = params.entrySet().stream()
   .map(entry -> new BasicNameValuePair(entry.getKey(), entry.getValue()))
   .collect(Collectors.toList());

URLEncodedUtils.format(nameValuePairs, Charset.forName("UTF-8"));
public String getQueryString(HttpServletRequest request, String encoding) {
    Map<String, String[]> parameters = request.getParameterMap();

    return parameters.entrySet().stream()
            .flatMap(entry -> encodeMultiParameter(entry.getKey(), entry.getValue(), encoding))
            .reduce((param1, param2) -> param1 + "&" + param2)
            .orElse("");
}

private Stream<String> encodeMultiParameter(String key, String[] values, String encoding) {
    return Stream.of(values).map(value -> encodeSingleParameter(key, value, encoding));
}

private String encodeSingleParameter(String key, String value, String encoding) {
    return urlEncode(key, encoding) + "=" + urlEncode(value, encoding);
}

private String urlEncode(String value, String encoding) {
    try {
        return URLEncoder.encode(value, encoding);
    } catch (UnsupportedEncodingException e) {
        throw new IllegalArgumentException("Cannot url encode " + value, e);
    }
}
 <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5</version>
 </dependency>
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
public static void parseAndFormatExample() throws UnsupportedEncodingException {
        final String queryString = "nonce=12345&redirectCallbackUrl=http://www.bbc.co.uk";
        System.out.println(queryString);
        // => nonce=12345&redirectCallbackUrl=http://www.bbc.co.uk

        final List<NameValuePair> params =
                URLEncodedUtils.parse(queryString, StandardCharsets.UTF_8);
        // List<NameValuePair> params = URLEncodedUtils.parse(new URI(url), "UTF-8");

        for (final NameValuePair param : params) {
            System.out.println(param.getName() + " : " + param.getValue());
            // => nonce : 12345
            // => redirectCallbackUrl : http://www.bbc.co.uk
        }

        final String newQueryStringEncoded =
                URLEncodedUtils.format(params, StandardCharsets.UTF_8);


        // decode when printing to screen
        final String newQueryStringDecoded =
                URLDecoder.decode(newQueryStringEncoded, StandardCharsets.UTF_8.toString());
        System.out.println(newQueryStringDecoded);
        // => nonce=12345&redirectCallbackUrl=http://www.bbc.co.uk
    }
 protected String formatQueryParams(Map<String, String> params) {
      return params.entrySet().stream()
          .map(p -> p.getKey() + "=" + p.getValue())
          .reduce((p1, p2) -> p1 + "&" + p2)
          .map(s -> "?" + s)
          .orElse("");
  }
map.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&"))
Map<String, String> map = new HashMap<>();

map.put("param1", "12");
map.put("param2", "cat");

String output = "someUrl?";
output += map.entrySet()
    .stream()
    .map(x -> x.getKey() + "=" + x.getValue() + "&")
    .collect(Collectors.joining("&"));

System.out.println(output.substring(0, output.length() -1));
map
  .entrySet()
  .stream()
  .map(e -> e.getKey() + "=" + e.getValue())
  .collect(Collectors.joining("&"));
final Map<String, String> map = new HashMap<>();
map.put("param1", "cat");
map.put("param2", "12");

final Uri uri = 
    map.entrySet().stream().collect(
        () -> Uri.parse("relativeUrl").buildUpon(),
        (builder, e) -> builder.appendQueryParameter(e.getKey(), e.getValue()),
        (b1, b2) -> { throw new UnsupportedOperationException(); }
    ).build();

//Or, if you consider it more readable...
final Uri.Builder builder = Uri.parse("relativeUrl").buildUpon();
map.entrySet().forEach(e -> builder.appendQueryParameter(e.getKey(), e.getValue())
final Uri uri = builder.build();

//...    

assertEquals(Uri.parse("relativeUrl?param1=cat&param2=12"), uri);
public static String toUrlEncode(Map<String, Object> map) {
    StringBuilder sb = new StringBuilder();
    map.entrySet().stream()
            .forEach(entry
                    -> (entry.getValue() == null
                    ? sb.append(entry.getKey())
                    : sb.append(entry.getKey())
                            .append('=')
                            .append(URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8)))
                    .append('&')
            );
    sb.delete(sb.length() - 1, sb.length());
    return sb.toString();
}
MultiValueMap<String, String> params =  new LinkedMultiValueMap<>();
String urlQueryString = params.entrySet()
            .stream()
            .flatMap(stringListEntry -> stringListEntry.getValue()
                    .stream()
                    .map(s -> UriUtils.encode(stringListEntry.getKey(), StandardCharsets.UTF_8.toString()) + "=" +
                            UriUtils.encode(s, StandardCharsets.UTF_8.toString())))
            .collect(Collectors.joining("&"));
mapOf(
  "param1" to 12,
  "param2" to "cat"
).map { "${it.key}=${it.value}" }
  .joinToString("&")