如何将POJO转换为MultiValueMap<String,String>?



我想将POJO转换为MultiValueMap<String, String>(RequestParams)。

POJO类:

public class Foo {
String fooStr;
int fooInt;
List<String> fooList;
}

转换代码:

public static MultiValueMap<String, String> convert( Object obj ) {
MultiValueMap<String, String> requestParamMultiValueMap = new LinkedMultiValueMap<>();

Map<String, String> requestParamMap = new ObjectMapper()
.convertValue( obj, new TypeReference<Map<String, String>>() {} ); // Exception occurs here
requestParamMultiValueMap.setAll( requestParamMap );

return requestParamMultiValueMap;
}

Foo类只有String成员变量时,没有关系,但Foo类有List<String>成员变量时,导致

IllegalArgumentException: 
Cannot deserialize value of type java.lang.String
from Array value (token JsonToken.START_ARRAY).

如何将POJO与List<String>字段转换为MultiValueMap使用杰克逊?

如果没有自定义,这是不可能自动完成的,因为这个问题太宽泛了:每个类型都需要转换为字符串列表,这不是很明显。这里我们有一些简单的情况(整数和字符串),但通常最好控制这种转换。

这里有一个简单的例子,首先我们做一个默认的转换到Map<String, Object>,由Jackson自然处理;然后是自定义if-else步骤,其中每种类型都经过特殊的转换。应该扩展此步骤以适应应用程序的确切需求(和类型)。我想适当的测试覆盖率会起到作用,因为在这种情况下,我们不能100%依赖静态类型。

重要的是要注意,如果Collection有其他集合作为元素,结果取决于每个特定的集合"toString"方法实现,这可能会产生意想不到的结果。

class TestJacksonConvert {
private static ObjectMapper OM = new ObjectMapper();
@Test
void test() {
var foo = new Foo();
foo.fooStr = "abc";
foo.fooInt = 21;
foo.fooList = List.of("a", "B", "c");
var converted = convert(foo);
assertEquals(
converted,
Map.of(
"fooStr", List.of("abc"),
"fooInt", List.of("21"),
"fooList", List.of("a", "B", "c")
)
);
}
public static LinkedMultiValueMap<String, String> convert(Object obj) {
var multiMap = new LinkedMultiValueMap<String, String>();
Map<String, Object> map = OM.convertValue(obj, new TypeReference<>() {});
map.forEach((key, value) -> {
if (value instanceof Collection<?> collection) {
multiMap.put(key, collection.stream().map(Object::toString).toList());
} else if (value != null) {
multiMap.put(key, List.of(value.toString()));
}
});
return multiMap;
}
}

这可能有点慢,但你可以试试。

public MultiValueMap<String, String> convertToMultiValueMap(Object pojo) {
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
Field[] fields = pojo.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String key = field.getName();
Object value = field.get(pojo);
if (value != null) {
map.add(key, value.toString());
}
}
return map;
}

该方法使用反射获取POJO中所有字段的列表,并将每个字段作为键值对添加到映射中。

相关内容

最新更新