如何在Java中将对象转换为查询字符串?

8
我正在尝试将以下对象转换为查询字符串,以便与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项目中用于Junit测试中的GET请求?

你是想要“自动”完成这个过程,还是手动构建键/值对?也就是说,你是想从任意对象中获取字段/值并将它们转换为查询字符串,还是只想从一个已知的、可硬编码的类中创建查询? - Toby Eggitt
是的,我正在尝试自动完成。我不想为每个参数编写查询参数。 - dev
你可以创建自己的实用方法,使用反射来构建查询字符串。 - shark1608
4个回答

3
为什么要先将数据类型转换为Map,再转换为MultiValueMap,而不是直接构建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();

我们可以使用这个方法。但是如果对象中有很多参数怎么办?那么对于每个单独的对象,我们都需要编写查询参数。这是更好的方法吗? - dev
Web服务器通常会限制URL的长度,因此您可以添加到URL的查询参数数量是有限制的。如果您确实需要发送具有大量值的对象,则应使用POST而不是GET,然后有效载荷甚至可以是复杂嵌套的值,例如XML或JSON。 - Andreas
如何处理具有列表和映射的20个以上参数对象?有更好的方法吗? - Buben Ivanov
@BubenIvanov 如果您有问题,应该创建一个问题,并提供比您在评论中提供的更多信息,因为我不知道您打算如何将“列表和映射”应用于此。 - Andreas

3
你可以编写自己的方法,使用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);
}

我参考了你的答案,为了更好地阐明,我发表了我的答案。 - silentsudo
它可以工作,但你应该写queryString = queryString.concat(f.getName() + "=" + String.valueOf(f.get(o)) + "&");而不是queryString += queryString.concat(f.getName() + "=" + String.valueOf(f.get(o)) + "&");(去掉“+”),否则每次想要添加一个字段时,它会将自身连接起来。 - pacataque

1

0

这是我会做的方式,

创建Map,填充并迭代Map项,并将其附加到构建器中,这对我来说似乎很有效。它不包括对嵌套对象的支持。使用递归应该很简单。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接