过滤器中修改响应体后,前端无法正常解析,求教如何处理?
在过滤器中修改响应体后,前端无法正常解析返回的Json对象。这个过滤器是为了实现把带id的Long字段转换成String再返回给前端。
@Component
@Slf4j
public class LongTypeFilter extends OncePerRequestFilter {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
log.debug("进入过滤器");
// 使用 ContentCachingResponseWrapper 包装响应
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
// 过滤器链继续
filterChain.doFilter(request, responseWrapper);
// 获取原始的响应数据
byte[] responseBody = responseWrapper.getContentAsByteArray();
// 获取原始响应的字符编码
String charset = response.getCharacterEncoding();
String contentType = response.getContentType();
// 判断是否需要进行 JSON 数据转换
if (contentType != null && contentType.startsWith(MediaType.APPLICATION_JSON_VALUE)) {
// 将原始响应数据转换为 JsonNode
JsonNode rootNode = objectMapper.readTree(new String(responseBody, charset));
// 判断是否包含 RespResult 对象
if (rootNode.has("code") && rootNode.has("msg") && rootNode.has("result")) {
JsonNode resultNode = rootNode.get("result");
// 判断 result 属性是否为对象,并且包含 Long 类型字段
checkAndConvertLongToString(resultNode);
}
log.debug(rootNode.toString());
// 将修改后的数据写回响应
String modifiedResponse = rootNode.toString();
//responseWrapper.setContentType(MediaType.APPLICATION_JSON_VALUE + ";charset=" + charset);
byte[] modifiedBytes = modifiedResponse.getBytes(charset);
responseWrapper.setContentLength(modifiedBytes.length);
responseWrapper.getWriter().write(modifiedResponse);
responseWrapper.copyBodyToResponse();
log.debug(response.getContentType());
} else {
// 非 JSON 格式的响应数据,直接写回响应
responseWrapper.copyBodyToResponse();
}
}
private void checkAndConvertLongToString(JsonNode node) {
if (node.isArray()) {
// 如果是数组,遍历数组内的元素
for (JsonNode arrayElement : node) {
if (arrayElement.isObject()) {
// 如果数组元素是对象,递归调用处理对象
checkAndConvertLongToString(arrayElement);
}
}
} else if (node.isObject()) {
// 如果是对象,继续处理对象内的字段
Iterator<String> fieldNames = node.fieldNames();
while (fieldNames.hasNext()) {
String fieldName = fieldNames.next();
JsonNode field = node.get(fieldName);
if (field != null) {
if (field.isLong() && field.canConvertToLong() && field.asLong() > Math.pow(2, 53) - 1) {
((ObjectNode) node).putPOJO(fieldName, String.valueOf(field.asLong()));
} else if (field.isObject()) {
checkAndConvertLongToString(field);
}
}
}
}
}
}
尝试了重新设置ContentType不行,ContentLength应该也没问题吧。前端拿到的返回数据是这样的。
{data: '{"code":200,"msg":"访问成功","result":[{"id":101433906…ice":0.02,"courseSort":3}]}],"time":"2023-12-19"}', status: 200, statusText: '', headers: AxiosHeaders...}
回复
1个回答
test
2024-06-23
直接使用Jackson2ObjectMapperBuilderCustomizer给Jackson 注册long序列化为string的序列化器不就行了吗,要这么大费周章从response读出来再写回去。
回复
适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容