【问题标题】:How to convert object to query string in Java?如何在Java中将对象转换为查询字符串?
【发布时间】:2018-09-25 21:28:33
【问题描述】:

我正在尝试将以下对象转换为查询字符串,以便可以与 GET 请求一起使用。

Class A {
  String prop1;
  String prop2;
  Date date1;
  Date date2;
  ClassB objB;
}

Class B {
 String prop3;
 String prop4;
}

我们可以将第一个对象转换为 Map 然后将 map 转换为 MultiValueMap 并使用 URIComponentsBuilder.fromHttpUrl("httpL//example.com").queryParams(multiValueMap).build();

是否有更短更好的方法将对象转换为查询字符串,以便在 Spring Project 中与 GET 请求一起用于 Junit 测试?

【问题讨论】:

  • 您是要“自动”执行此操作,还是可以手动构建键/值对?也就是说,您是否尝试从任意对象中获取字段/值并将它们转换为查询字符串?或者您只是想从一个众所周知的、可硬编码的类创建查询?
  • 是的,我正在尝试自动执行。我不想为每个参数写查询参数。
  • 您可以创建自己的实用方法,使用反射来构建查询字符串。

标签: java spring junit


【解决方案1】:

为什么要转换为Map 然后MultiValueMap,而不是直接构建它?

DateFormat dateFmt = new SimpleDateFormat("whatever date format you want");
URIComponentsBuilder.fromHttpUrl("httpL//example.com")
                    .queryParam("prop1", a.prop1)
                    .queryParam("prop2", a.prop2)
                    .queryParam("date1", dateFmt.format(a.date1))
                    .queryParam("date2", dateFmt.format(a.date2))
                    .queryParam("prop3", a.objB.prop3)
                    .queryParam("prop4", a.objB.prop4)
                    .build();

【讨论】:

  • 我们可以使用这个。但是如果对象中有很多参数怎么办?然后对于每个对象,我们需要编写查询参数。这是更好的方法吗?
  • Web 服务器通常会限制 URL 的长度,因此对可以添加到 URL 的查询参数的数量是有限制的。如果您确实需要发送具有大量值的对象,则应该使用 POST,而不是 GET,然后有效负载甚至可以是复杂的嵌套值,例如XML 或 JSON。
  • 以及如何处理带有列表和地图的 20+ 参数对象?有没有更好的办法?
  • @BubenIvanov 如果您有问题,您应该创建一个问题,并提供比您在评论中所做的更多的信息,因为我不知道您打算如何将“列表和地图”应用于此.
【解决方案2】:

您可以编写自己的方法来使用java.lang.reflect。这是一个例子

public static String getRequestString(String urlString, Class clazz, Object o){
    String queryString = "?";

    try {
        for (Field f : clazz.getDeclaredFields()) {
            f.setAccessible(true);
            queryString += queryString.concat(f.getName() + "=" + String.valueOf(f.get(o)) + "&");
        }
    }catch (Exception e){
        e.printStackTrace();
    }

    return urlString + queryString.substring(0,queryString.length()-1);
}

【讨论】:

  • 我参考了你的回答并发布了我的答案以更清晰
  • 它可以工作,但你应该写 queryString = queryString.concat(f.getName() + "=" + String.valueOf(f.get(o)) + "&");而不是 queryString += queryString.concat(f.getName() + "=" + String.valueOf(f.get(o)) + "&"); (删除“+”)否则每次你想添加一个字段时你都会连接自己
【解决方案3】:

OpenFeign 有注解@QueryMap 可以根据对象属性动态生成查询参数:

public interface Api {
  @RequestLine("GET /find")
  V find(@QueryMap CustomPojo customPojo);
}

查看更多信息: https://github.com/OpenFeign/feign#dynamic-query-parameters

【讨论】:

    【解决方案4】:

    我会这样做,

    创建地图,填充然后迭代地图项目并附加到构建器这似乎对我有用。它不包括对嵌套对象的支持。递归应该很简单。

    public String getRequestString(Class clazz, Object o) {
            StringBuilder queryStringBuilder = new StringBuilder();
            final Map<String, String> queryParams = new LinkedHashMap<>();
    
            try {
                for (Field f : clazz.getDeclaredFields()) {
                    f.setAccessible(true);
                    queryParams.put(f.getName(), String.valueOf(f.get(o)));
                }
                for (Map.Entry<String, String> entry : queryParams.entrySet()) {
                    queryStringBuilder.append(testStringUtils.toSnakeCase(entry.getKey()));
                    queryStringBuilder.append("=");
                    queryStringBuilder.append(entry.getValue());
                    queryStringBuilder.append("&");
                }
                logger.info("Map: " + queryParams);
            } catch (Exception e) {
                e.printStackTrace();
            }
            final String queryString = queryStringBuilder.toString();
            logger.info("Query string : " + queryString.substring(0, queryString.length() - 1));
            return "?" + queryString.substring(0, queryString.length() - 1);
    

    【讨论】:

      猜你喜欢
      • 2016-10-01
      • 2013-02-16
      • 1970-01-01
      • 1970-01-01
      • 2016-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-24
      相关资源
      最近更新 更多