Spring Boot 统一设置Json数据返回风格(Java驼峰命名转下划线,解决数字转换缺陷)
一般普通转化使用:
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
/**
* 统一输出风格
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (int i = 0; i < converters.size(); i++) {
if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
ObjectMapper objectMapper = new ObjectMapper();
// 统一返回数据的输出风格
objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy());
//普通转换: firstName --> first_name
//如果字段值为null 不返回
//objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(objectMapper);
converters.set(i, converter);
break;
}
}
}
}
解决带数字的问题
WebMvcConfig
import com.csc.config.webMvcConfig.PropertyNamingStrategyConfig;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.util.List;
import java.util.TimeZone;
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
/**
* 统一输出风格
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (int i = 0; i < converters.size(); i++) {
if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
ObjectMapper objectMapper = new ObjectMapper();
// 统一返回数据的输出风格
//objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy());
//普通转换: firstName --> first_name
//缺陷: 如: returnThisYear20 只能转换成:return_this_year20 可是我们想要的结果是:return_this_year_20
//使用自己重写的方法
objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategyConfig.NumCaseStrategy());
//如果字段值为null 不返回
//objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(objectMapper);
converters.set(i, converter);
break;
}
}
}
}
PropertyNamingStrategyConfig
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
import java.io.Serializable;
import java.util.regex.Pattern;
public class PropertyNamingStrategyConfig implements Serializable {
public static final PropertyNamingStrategy SNAKE_CASE = new PropertyNamingStrategy.SnakeCaseStrategy();
public static final PropertyNamingStrategy UPPER_CAMEL_CASE = new PropertyNamingStrategy.UpperCamelCaseStrategy();
public static final PropertyNamingStrategy LOWER_CAMEL_CASE = new PropertyNamingStrategy();
public static final PropertyNamingStrategy LOWER_CASE = new PropertyNamingStrategy.LowerCaseStrategy();
public static final PropertyNamingStrategy KEBAB_CASE = new PropertyNamingStrategy.KebabCaseStrategy();
//依照 PropertyNamingStrategy.SnakeCaseStrategy() 新增数字方法
public static final PropertyNamingStrategy NUM_CASE = new PropertyNamingStrategyConfig.NumCaseStrategy();
/** @deprecated */
@Deprecated
public static final PropertyNamingStrategy CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES;
/** @deprecated */
@Deprecated
public static final PropertyNamingStrategy PASCAL_CASE_TO_CAMEL_CASE;
public PropertyNamingStrategyConfig() {
}
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return defaultName;
}
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return defaultName;
}
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return defaultName;
}
public String nameForConstructorParameter(MapperConfig<?> config, AnnotatedParameter ctorParam, String defaultName) {
return defaultName;
}
static {
CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES = SNAKE_CASE;
PASCAL_CASE_TO_CAMEL_CASE = UPPER_CAMEL_CASE;
}
/** @deprecated */
@Deprecated
public static class PascalCaseStrategy extends PropertyNamingStrategy.UpperCamelCaseStrategy {
public PascalCaseStrategy() {
}
}
/** @deprecated */
@Deprecated
public static class LowerCaseWithUnderscoresStrategy extends PropertyNamingStrategy.SnakeCaseStrategy {
public LowerCaseWithUnderscoresStrategy() {
}
}
public static class KebabCaseStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase {
public KebabCaseStrategy() {
}
public String translate(String input) {
if (input == null) {
return input;
} else {
int length = input.length();
if (length == 0) {
return input;
} else {
StringBuilder result = new StringBuilder(length + (length >> 1));
int upperCount = 0;
for(int i = 0; i < length; ++i) {
char ch = input.charAt(i);
char lc = Character.toLowerCase(ch);
if (lc == ch) {
if (upperCount > 1) {
result.insert(result.length() - 1, '-');
}
upperCount = 0;
} else {
if (upperCount == 0 && i > 0) {
result.append('-');
}
++upperCount;
}
result.append(lc);
}
return result.toString();
}
}
}
}
public static class LowerCaseStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase {
public LowerCaseStrategy() {
}
public String translate(String input) {
return input.toLowerCase();
}
}
public static class UpperCamelCaseStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase {
public UpperCamelCaseStrategy() {
}
public String translate(String input) {
if (input != null && input.length() != 0) {
char c = input.charAt(0);
char uc = Character.toUpperCase(c);
if (c == uc) {
return input;
} else {
StringBuilder sb = new StringBuilder(input);
sb.setCharAt(0, uc);
return sb.toString();
}
} else {
return input;
}
}
}
public static class SnakeCaseStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase {
public SnakeCaseStrategy() {
}
public String translate(String input) {
if (input == null) {
return input;
} else {
int length = input.length();
StringBuilder result = new StringBuilder(length * 2);
int resultLength = 0;
boolean wasPrevTranslated = false;
for(int i = 0; i < length; ++i) {
char c = input.charAt(i);
if (i > 0 || c != '_') {
if (Character.isUpperCase(c)) {
if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_') {
result.append('_');
++resultLength;
}
c = Character.toLowerCase(c);
wasPrevTranslated = true;
} else {
wasPrevTranslated = false;
}
result.append(c);
++resultLength;
}
}
return resultLength > 0 ? result.toString() : input;
}
}
}
public abstract static class PropertyNamingStrategyBase extends PropertyNamingStrategy {
public PropertyNamingStrategyBase() {
}
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return this.translate(defaultName);
}
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return this.translate(defaultName);
}
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return this.translate(defaultName);
}
public String nameForConstructorParameter(MapperConfig<?> config, AnnotatedParameter ctorParam, String defaultName) {
return this.translate(defaultName);
}
public abstract String translate(String var1);
}
public static class NumCaseStrategy extends PropertyNamingStrategy.SnakeCaseStrategy {
public NumCaseStrategy() {
}
public String translate(String input) {
if (input == null) {
return input;
} else {
int length = input.length();
StringBuilder result = new StringBuilder(length * 2);
int resultLength = 0;
boolean wasPrevTranslated = false;
for(int i = 0; i < length; ++i) {
char c = input.charAt(i);
if (i > 0 || c != '_') {
if (Character.isUpperCase(c)) {
if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_') {
result.append('_');
++resultLength;
}
c = Character.toLowerCase(c);
wasPrevTranslated = true;
} else if(!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_' && Pattern.compile("^-?\\d+(\\.\\d+)?$").matcher(String.valueOf(c)).matches() && !Pattern.compile("^-?\\d+(\\.\\d+)?$").matcher(String.valueOf(input.charAt(i-1))).matches() ){
//新增数字判断
// Pattern.compile("^-?\\d+(\\.\\d+)?$").matcher(String.valueOf(c)).matches() && !Pattern.compile("^-?\\d+(\\.\\d+)?$").matcher(String.valueOf(input.charAt(i-1))).matches()
// 表示 用正则表达式判断 当前位是数字 且 前一位不是数字
result.append('_');
++resultLength;
} else {
wasPrevTranslated = false;
}
result.append(c);
++resultLength;
}
}
return resultLength > 0 ? result.toString() : input;
}
}
}
}
这样对于一般的转化都没问题
如:firstName转成first_name,
firstName20转化成first_name_20,
first20Name转化成first_20_name
这当中还有转换缺陷在于:
1.两个相连接的大写字母不能很好转换:
对个别的类似于: firstNameTTest只能转换成first_name_ttest,而我们想要的结果是first_name_t_test,这种情况下我暂时使用的方法是在实体类字段上面加@JsonProperty(“first_name_t_test”)注解来转化
2.一个大写字母后跟一个数字不能很好地转换:
对于个别的如:firstNameT20只能转换成first_name_t20,而我们想要的结果是first_name_t_20,这种情况下我暂时使用的方法是在实体类字段上加上@JsonProperty(“first_name_t_20”)注解来转化
最后:希望大家有好的解决这两个缺陷的方法,一起来沟通交流学习