前言 使用SpringBoot查询数据库,数据库中字段是首字母大写,实体类中也是使用了首字母大写,但是返回前端的数据json字符串时,出现了大写字母变为小写字母的情况。比如:
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 @Autowired private MediumRepo mediumRepo;@Autowired private GroupInfoRepo groupInfoRepo;@RequestMapping(value = "siteList") public JSONObject siteList () { JSONObject result=new JSONObject (); try { List<Medium> mediumList=mediumRepo.findAll(); JSONObject mediumObj=new JSONObject (); JSONObject tempObj=new JSONObject (); mediumList.stream().forEach(medium -> { mediumObj.put(medium.getMediumType().toString(),medium); }); result.put("mediumList" ,mediumObj); List<GroupInfo> groupInfos=groupInfoRepo.findAll(); JSONObject groupObj=new JSONObject (); groupInfos.stream().forEach(groupInfo -> { groupObj.put(groupInfo.getGroupId().toString(),groupInfo.getGroupName()); }); result.put("groupList" ,groupObj); }catch (Exception e){ logger.error("siteList" ,e); } return result; }
最后返回给前台的json字符串清一色的首字母变成了小写。
[解决方式]
1.在属性上添加@JsonProperty注解 在属性上添加@JsonProperty注解,在set和get方法上添加@JsonIgnore,@JsonProperty和@JsonIgnore一起使用,只使用一个无效。
1 2 3 4 5 6 7 8 9 10 11 @JsonProperty(value = "MediumStr") private String MediumStr;@JsonIgnore public String getMediumStr () { return MediumStr; } public void setMediumStr (String mediumStr) { MediumStr = mediumStr; }
2.直接将@JsonProperty注解到get,set方法上 1 2 3 4 @JsonProperty(value = "MediumStr") public String getMediumStr () { return MediumStr; }
3.使用FastJSON替换默认的json转换器 根据参考文章4和5,还可以使用FastJSON替换默认的json转换器
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 package com.bibichuan.phemsjava.boot;import com.alibaba.fastjson.serializer.SerializerFeature;import com.alibaba.fastjson.support.config.FastJsonConfig;import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;import org.springframework.context.annotation.Configuration;import org.springframework.http.converter.HttpMessageConverter;import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter;import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;import org.springframework.web.servlet.config.annotation.CorsRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.Iterator;import java.util.List;@Configuration public class WebMvcCon implements WebMvcConfigurer { @Override public void addCorsMappings (CorsRegistry registry) { registry.addMapping("/**" ) .allowedOrigins("*" ) .allowCredentials(true ) .allowedMethods("GET" , "POST" , "DELETE" , "PUT" ,"PATCH" ) .maxAge(3600 ); } @Override public void configureMessageConverters (List<HttpMessageConverter<?>> converters) { Iterator<HttpMessageConverter<?>> iterator = converters.iterator(); while (iterator.hasNext()){ HttpMessageConverter<?> converter = iterator.next(); if (converter instanceof MappingJackson2HttpMessageConverter){ iterator.remove(); } } FastJsonHttpMessageConverter fastConverter=new FastJsonHttpMessageConverter (); FastJsonConfig fastJsonConfig=new FastJsonConfig (); fastJsonConfig.setSerializerFeatures( SerializerFeature.PrettyFormat ); fastConverter.setFastJsonConfig(fastJsonConfig); converters.add(fastConverter); } @Override public void extendMessageConverters (List<HttpMessageConverter<?>> converters) { for (HttpMessageConverter<?> messageConverter : converters) { System.out.println(messageConverter); } } }
问题: (1) Spring Boot配置FastJson报错’Content-Type’ cannot contain wildcard type ‘*’
在WebMvcCon类中增加如下代码:
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 @Override public void configureMessageConverters (List<HttpMessageConverter<?>> converters) { Iterator<HttpMessageConverter<?>> iterator = converters.iterator(); while (iterator.hasNext()){ HttpMessageConverter<?> converter = iterator.next(); if (converter instanceof MappingJackson2HttpMessageConverter){ iterator.remove(); } } FastJsonHttpMessageConverter fastConverter=new FastJsonHttpMessageConverter (); FastJsonConfig config = new FastJsonConfig (); config.setSerializerFeatures(SerializerFeature.QuoteFieldNames, SerializerFeature.PrettyFormat, SerializerFeature.WriteEnumUsingToString, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.DisableCircularReferenceDetect); List<MediaType> supportedMediaTypes = new ArrayList <>(); supportedMediaTypes.add(MediaType.APPLICATION_JSON); supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); 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); fastConverter.setSupportedMediaTypes(supportedMediaTypes); fastConverter.setFastJsonConfig(config); converters.add(fastConverter); }
(2) 不知道为什么,还是返回的是小写字母。就算单独写一个Bean也是不行的。不知道什么原因。
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 package com.bibichuan.phemsjava.boot;import com.alibaba.fastjson.serializer.SerializerFeature;import com.alibaba.fastjson.support.config.FastJsonConfig;import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;import org.springframework.boot.autoconfigure.http.HttpMessageConverters;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.MediaType;import java.util.ArrayList;import java.util.List;@Configuration public class MessageConverConf { @Bean public HttpMessageConverters fastJsonHttpMessageConverters () { FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter (); FastJsonConfig fastJsonConfig = new FastJsonConfig (); fastJsonConfig.setSerializerFeatures( SerializerFeature.PrettyFormat, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty ); List<MediaType> fastMediaTypes = new ArrayList <MediaType>(); fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); fastConverter.setSupportedMediaTypes(fastMediaTypes); fastConverter.setFastJsonConfig(fastJsonConfig); return new HttpMessageConverters (fastConverter); } }
(3) 原来是要在@Entity注解的实体类的属性上使用 @JSONField(name=”SiteNo”) ,就可以实现了首字母大写。
进一步的问题,如果我不使用每一个属性都多加一个@JSONField注解的方式,实现直接的进行首字母大写转换。
(4) 使用@JsonProperty注解之后,虽然将返回的字段首字母进行了大小,但是出现新的问题,就是小写的字段还是存在,也就是返回了两个数据,一个大写,一个小写
【解决方法】 如果放到属性上不起作用,或者同时返回了大小写,那么就尝试放在get方法上
4.Spring的PropertyNamingStrategy配置 随着进一步资料查询,可以配置命名策略,我发现了一个在application.yml中通过配置PropertyNamingStrategy方法。答案是有的。只需要配置application.yml内容:
1 2 3 spring: jackson: property-naming-strategy: UPPER_CAMEL_CASE
还有其他的一些命名策略:
(1) LOWER_CASE
Naming convention in which all words of the logical name are in lower case, and no separator is used between words.
(2) KEBAB_CASE
Naming convention used in languages like Lisp, where words are in lower-case letters, separated by hyphens.
(3) LOWER_CAMEL_CASE
Naming convention used in Java, where words other than first are capitalized and no separator is used between words.
(4) LOWER_CASE
Naming convention in which all words of the logical name are in lower case, and no separator is used between words.
(5) SNAKE_CASE
Naming convention used in languages like C, where words are in lower-case letters, separated by underscores.
有下面几种方式: (1)属性名称:@JsonProperty (2)预定义命名策略,只需要作用于某个类:@JsonNaming (3)自定义命名策略:PropertyNamingStrategy
5.使用Bean注入的方式 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 package com.bibichuan.phemsjava.boot;import com.fasterxml.jackson.annotation.JsonInclude;import com.fasterxml.jackson.core.JsonGenerator;import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.databind.DeserializationFeature;import com.fasterxml.jackson.databind.JsonSerializer;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializerProvider;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;import java.io.IOException;@Configuration public class BeanConf { @Bean @Primary @ConditionalOnMissingBean(ObjectMapper.class) public ObjectMapper jacksonObjectMapper (Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.createXmlMapper(false ).build(); objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true ); objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true ); objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer <Object>() { @Override public void serialize (Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeString("" ); } }); return objectMapper; } }
总结 基础知识还是不牢啊,总是出现问题再去找答案,非常的浪费时间,需要系统性,综合性的对SpringBoot进行学习,才能进行更好的开发。
6.@RequestBody属性名大写注入为空
7.使用@JSONFiled 使用这个注解主要就是在使用FastJSON序列化的时候,出现首字母大写变小写的问题。在fastjson1.x的时候,在属性上注解@JSONField就可以指定序列化的时候的内容,但是在FastJSON2.x的时候,这个注解注解到属性上不再起作用了,必须要注解到getter方法上,这个暂时还没有解决
8.自定义命名策略 编写自定义命名策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class CustomPropertyNamingStrategy extends PropertyNamingStrategies .NamingBase { @Override public String nameForField (MapperConfig<?> config, AnnotatedField field, String defaultName) { return translate(defaultName); } @Override public String nameForGetterMethod (MapperConfig<?> config, AnnotatedMethod method, String defaultName) { return translate(defaultName); } @Override public String translate (String input) { return input; } }
ObjectMapper 注入自定义命名策略
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 @Configuration public class SpringBeanConfiguration { @Bean public ObjectMapper objectMapper () { ObjectMapper objectMapper = new ObjectMapper (); objectMapper.setPropertyNamingStrategy(new CustomPropertyNamingStrategy ()); objectMapper.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN); objectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS); objectMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false ); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false ); objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false ); objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES, false ); objectMapper.setDateFormat(new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss" )); JavaTimeModule javaTimeModule = new JavaTimeModule (); javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer (DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss" ))); javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer (DateTimeFormatter.ofPattern("yyyy-MM-dd" ))); javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer (DateTimeFormatter.ofPattern("HH:mm:ss" ))); javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer (DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss" ))); javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer (DateTimeFormatter.ofPattern("yyyy-MM-dd" ))); javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer (DateTimeFormatter.ofPattern("HH:mm:ss" ))); objectMapper.registerModule(javaTimeModule); return objectMapper; } }
参考文章:
【1】.
jackson自定义策略 一.属性名称@JsonProperty;二 .预定义命名策略PropertyNamingStrategy;三.自定义PropertyNamingStrategy
【2】.
Jackson修改字段名和自定义命名策略 通过实现 PropertyNamingStrategyBase 进行自定义命名策略的实现
9.StdSerializer 使用 StdSerializer 注入自定义的序列化和反序列化的类,实现单独对某一个类进行特殊的序列化。