您可以AbstractHttpMessageConverter针对您的问题使用自定义映射操作。
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;
@Component
public class CustomMessageConverter extends AbstractHttpMessageConverter<Map<String, Map<String, Object>>> {
public CustomMessageConverter() {
super(MediaType.APPLICATION_JSON);
}
@Override
protected boolean supports(Class<?> clazz) {
return HashMap.class.isAssignableFrom(clazz);
}
@Override
protected Map<String, Map<String, Object>> readInternal(Class<? extends Map<String, Map<String, Object>>> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return null;
}
@Override
protected void writeInternal(Map<String, Map<String, Object>> value, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
PrintStream printStream = new PrintStream(outputMessage.getBody());
printStream.print("{");
// track to put comma between items
boolean printedEntry = false;
for (Map.Entry<String, Map<String, Object>> entry : value.entrySet()) {
/* // if you want to disable null print uncomment it
if (entry.getValue() == null) {
continue;
}
*/
if (printedEntry) {
printStream.print(",");
}
printStream.print("\"" + entry.getKey() + "\":");
if (entry.getValue() == null) {
printStream.print("null");
continue;
}
// INNER ENTRY LOOP
printStream.print("{");
// track to put comma between items
boolean printedInnerEntry = false;
for (Map.Entry<String, Object> innerEntry : entry.getValue().entrySet()) {
if (printedInnerEntry) {
printStream.print(",");
}
printStream.print("\"" + innerEntry.getKey() + "\":");
printStream.print(innerEntry.getValue());
printedInnerEntry = true;
}
printStream.print("}");
printedEntry = true;
}
printStream.print("}");
}
}
测试
@RestController
public class HomeController {
@GetMapping
public ResponseEntity<Map<String, Map<String, Object>>> getComplexStructure() {
Map<String, Map<String, Object>> result = new HashMap<>();
Map<String, Object> innerItem1 = new HashMap<>();
innerItem1.put("bar1", "{\"item\": 12, \"list\": [1, 2]}");
innerItem1.put("bar2", "{\"item\": 22, \"test\": \"test@\"}");
result.put("foo1", innerItem1);
Map<String, Object> innerItem2 = new HashMap<>();
innerItem2.put("tail1", "{\"item\": 55}");
innerItem2.put("tail2", "{\"item\": 77}");
result.put("foo2", innerItem2);
return ResponseEntity.ok(result);
}
}
GET http://localhost:8080/
输出
{"foo1":{"bar1":{"item": 12, "list": [1, 2]},"bar2":{"item": 22, "test": "test@"}},"foo2":{"tail1":{"item": 55},"tail2":{"item": 77}}}
警告
我建议创建一个新类来操作这种特殊情况。因为HashMap是通用的,并且捕获了所有从HashMap. 因此,如果您想更喜欢这种方式,您可以更改以下代码。
创建一个新的返回类型HashMap<String, Map<String, Object>>
public class CustomMessage extends HashMap<String, Map<String, Object>> {
}
用下面的CustomMessageConverter改变supports方法。
@Override
protected boolean supports(Class<?> clazz) {
return CustomMessage.class.isAssignableFrom(clazz);
}
此外,您可以更改AbstractHttpMessageConverter<CustomMessage>而不是更改,AbstractHttpMessageConverter<Map<String, Map<String, Object>>>但这不是必需的。
使用这个新类更改返回类型。
public ResponseEntity<CustomMessage> getComplexStructure() {
CustomMessage result = new CustomMessage();
...
return ResponseEntity.ok(result);
}