偌大的城市,绵延无尽,并非是我眼见的让我停住了脚步,而是我所看不见的。——《海上钢琴师》
今天遇到这样一个问题:
序列化出现了与预期不一致的效果,重现代码很简单,就返回一个list
,包含几个对象
1 2 3 4 5
| @GetMapping public Result testQueryParam(CommonDTO commonDTO) { final UserDetail userDetail = UserDetail.builder().build(); return Result.ok().data(Arrays.asList(userDetail, userDetail, userDetail)); }
|
但可以看到我这里第一条数据是正确的,第二条开始就变成了{$ref: "$.data[0]"}
这是因为我们在使用fastjson
作为mvc
全局序列化框架的时候
在fastjson
中,会自动检测循环引用,并且输出为fastjson
专有的引用表示格式。但这个不能被其他JSON库识别,也不能被浏览器识别,所以fastjson
提供了关闭循环引用检测的功能。使用如下:
1 2 3
| import com.alibaba.fastjson.serializer.SerializerFeature;
JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
|
fastjson
文档链接:https://gitee.com/wenshao/fastjson/wikis/pages?sort_id=1591202&doc_id=10706
处理方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
| package com.ruben.simplescaffold.config;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ArrayUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.parser.ParserConfig; import com.alibaba.fastjson.serializer.SerializeConfig; import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.core.toolkit.LambdaUtils; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruben.simplescaffold.exception.PageException; import com.ruben.simplescaffold.handler.GlobalTimeResolver; import com.ruben.simplescaffold.utils.Opt; import org.apache.ibatis.reflection.property.PropertyNamer; import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver; import org.springframework.boot.web.servlet.MultipartConfigFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.util.unit.DataSize; import org.springframework.util.unit.DataUnit; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import javax.servlet.MultipartConfigElement; import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Stream;
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer {
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter(); List<MediaType> supportedMediaTypes = new ArrayList<>(); supportedMediaTypes.add(MediaType.APPLICATION_JSON); supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML); supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED); supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM); supportedMediaTypes.add(MediaType.APPLICATION_PDF); supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML); supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML); supportedMediaTypes.add(MediaType.APPLICATION_XML); supportedMediaTypes.add(MediaType.IMAGE_GIF); supportedMediaTypes.add(MediaType.IMAGE_JPEG); supportedMediaTypes.add(MediaType.IMAGE_PNG); supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM); supportedMediaTypes.add(MediaType.TEXT_HTML); supportedMediaTypes.add(MediaType.TEXT_MARKDOWN); supportedMediaTypes.add(MediaType.TEXT_PLAIN); supportedMediaTypes.add(MediaType.TEXT_XML); fastJsonConverter.setSupportedMediaTypes(supportedMediaTypes); FastJsonConfig fjc = new FastJsonConfig(); fjc.setSerializerFeatures(SerializerFeature.BrowserCompatible, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteEnumUsingToString); SerializeConfig serializeConfig = SerializeConfig.globalInstance; serializeConfig.put(LocalDateTime.class, (serializer, object, fieldName, fieldType, features) -> Opt.ofNullable(object).ifPresentOrElse(obj -> serializer.out.writeString(((LocalDateTime) obj).format(GlobalTimeResolver.DATE_TIME_FORMATTER)), serializer.out::writeNull)); fjc.setSerializeConfig(serializeConfig); ParserConfig parserConfig = ParserConfig.getGlobalInstance(); fjc.setParserConfig(parserConfig); fastJsonConverter.setFastJsonConfig(fjc); converters.add(fastJsonConverter); }
}
|
然后正常