首页 > 其他分享 >记一次springboot通过jackson渲染到前端,出现大写字母变成小写问题

记一次springboot通过jackson渲染到前端,出现大写字母变成小写问题

时间:2023-04-04 09:58:08浏览次数:43  
标签:environment jackson springboot method 大写字母 defaultName 小写 public

前言

最近业务部门接手了外包供应商的项目过来自己运维,该部门的小伙伴发现了一个问题,比如后端的DTO有个属性名为nPrice的字段,通过json渲染到前端后,变成nprice,而预期的字段是要为nPrice。于是他们就找到我们部门,希望我们能帮忙解决一下这个问题,本文就聊聊如何解决问题,至于为什么会出现这个问题,后面留个彩蛋

解法

注: 本文的json都是通过springboot默认的jackson进行渲染解析,因此本文的解法都是针对jackson

方法一:在属性字段上加@JsonProperty注解

示例

    @JsonProperty(value = "nPropriceFactory")
    private BigDecimal nPropriceFactory;

因为业务接手的项目的字段的属性大量都是首字母小写,第二个字母大写的形式,比如nHelloWorld,因此业务部门的小伙伴,觉得一个个加太麻烦了,有没有更简洁点办法。于是就有了第二种方法

方法二:通过自定义com.fasterxml.jackson.databind.PropertyNamingStrategy策略

具体逻辑形如如下

public class CustomPropertyNamingStrategy extends PropertyNamingStrategy {


    @Override
    public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
        if (isSpecialPropertyName(defaultName)) {
            //将属性的get方法去除get,然后首字母转小写
            return StringUtils.uncapitalize(method.getName().substring(3));
        }
        return super.nameForGetterMethod(config,method,defaultName);
    }



    @Override
    public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
        if (isSpecialPropertyName(defaultName)) {
            //将属性的set方法去除set,然后首字母转小写
            return StringUtils.uncapitalize(method.getName().substring(3));
        }
        return super.nameForSetterMethod(config,method,defaultName);
    }

  


}

在application.yml做如下配置

spring:
  jackson:
    property-naming-strategy: com.github.lybgeek.jackson.CustomPropertyNamingStrategy

这样就可以解决了,不过业务部门的研发,基本上都是被惯坏的小孩,为了让他们更方便的使用,我们就更近一步,也不要在yml进行配置了,让他们直接引入jar就好。于是我们做了如下操作

public final class EnvUtils {

    private EnvUtils(){}

    private static final String JACKSON_PROPERTY_NAMING_STRATEGY_KEY = "spring.jackson.property-naming-strategy";


    public static void postProcessEnvironment(ConfigurableEnvironment environment){
        String isCustomJsonFormatEnaled = environment.getProperty(CUSTOM_JSON_FORMAT_ENABLE_KEY,"true");
        if("true".equalsIgnoreCase(isCustomJsonFormatEnaled)){
            setCustomJacksonPropertyNamingStrategy(environment);
        }
    }

    private static void setCustomJacksonPropertyNamingStrategy(ConfigurableEnvironment environment) {
        MutablePropertySources propertySources = environment.getPropertySources();
        Map<String, Object> mapPropertySource = new HashMap<>();
        mapPropertySource.put(JACKSON_PROPERTY_NAMING_STRATEGY_KEY, CustomPropertyNamingStrategy.class.getName());
        PropertySource propertySource = new MapPropertySource("custom-json-format-properties",mapPropertySource);
        propertySources.addFirst(propertySource);
    }

}

public class CustomJacksonFormatEnvironmentApplicationContextInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        EnvUtils.postProcessEnvironment(environment);

    }
}

在resouce下新建META-INF/spring.factories,并指定如下内容

org.springframework.context.ApplicationContextInitializer=\
com.github.lybgeek.jackson.env.CustomJacksonFormatEnvironmentApplicationContextInitializer

自此业务部门只要引入这个包,就可以解决jackson渲染到前端,出现大写字母变成小写问题

:如果用实现org.springframework.boot.env.EnvironmentPostProcessor来实现属性配置也可以,不过要注意如果是使用springcloud,则可能会出现在配置在application.yml的属性,通过

environment.getProperty(CUSTOM_JSON_FORMAT_ENABLE_KEY);

拿不到值的情况。因此推荐用实现org.springframework.context.ApplicationContextInitializer来进行环境变量获取或者设置

总结

以上两种方式,一种是采用局部的方式,另一种是采用全局的方式,采用全局的方式,要做好测试,不然影响很大,我们采用全局的方式,一来是业务那边要求,二来是当时我们和业务部门做好沟通,我们根据他们的业务规则来做定制,并跟他们说明采用全局的方式可能遇到的问题。

至于为啥jackson渲染到前端,出现大写字母变成小写问题,大家如果有空debug跟到com.fasterxml.jackson.databind.util.BeanUtil#legacyManglePropertyName这个方法,应该就会有答案。如果没空的话,就可以查看如下链接
https://blog.csdn.net/weixin_42511702/article/details/112520749
进行解读

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-json-format

标签:environment,jackson,springboot,method,大写字母,defaultName,小写,public
From: https://www.cnblogs.com/linyb-geek/p/17030544.html

相关文章

  • Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
    如何阻止JavaSpringBootTest单元测试中包括多线程时,没跑完就结束了使用CountDownLatchCountDownLatch、CyclicBarrier使用区别多线程ThreadPoolTaskExecutor应用JavaBasePooledObjectFactory对象池化技术@SpringBootTestpublicclassPoolTest{@Test......
  • SpringBoot外部化配置定时任务cron表达式
    SpringBoot外部化配置定时任务cron表达式背景在日常开发中我们经常会使用到定时任务的情况,SpringBoot为我们很方便的集成了定时任务。我们只需要简单的几部就可以配置好一个定时任务。@ComponentpublicclassLocationTask{@Scheduled(cron="0/10****?")pu......
  • springboot 注解
    @RequestMapping:定义请求路径url@RequestParam:解决请求参数和形参变量名不一样问题,将指定名称的请求参数赋值给变量@RequestBody:将请求体中的json转换成java对象使用条件:1、有请求体。2、请求数据是json格式。@PathVariable注解:将路径指定占位符对应的参数值赋值给变量。@Response......
  • springboot整合JUnit
    步骤:导入测试对应的starter(springboot帮我们自动导入,纯手工创建时一定记得自己导入)测试类使用@SpringBootTest修饰使用自动装配的形式添加要测试的对象名称:@SpringBootTest类型:测试类注解位置:测试类定义上方作用:设置JUnit加载的SpringBoot启动类范例:@SpringBoot......
  • springboot请求响应
    springboot请求响应1.什么是请求?响应?请求:获取请求数据响应:设置响应数据2.原始方法获取请求数据Controller方法形参中声明HttpServletRequest对象调用对象的getParameter(参数名)这种方式复杂繁琐//@RequestMapping("/simpleParam")//原始方式//创建请求对......
  • Springboot JSON整合—官方原版
    SpringBoot提供与三个JSON映射库的集成:GsonJacksonJSON-BJackson是首选和默认库。一、Jackson提供了Jackson的自动配置,Jackson是springbootstarterjson的一部分。当Jackson在类路径上时,会自动配置一个ObjectMapperbean。提供了几个配置财产,用于自定义ObjectMapper的配置。1.......
  • 怎么在springboot中配置https证书的详细教程
    前言由于小程序需要https,然后之前申请的域名过期了,用了两年由于忘记续费要将域名赎回居然要1200....想了一下之前还有另一个域名,干脆就用这个域名弄个二级域名出来,所以二级域名建立出来后需要在springboot项目上开启https访问废话不多说,开整在阿里云新建二级域名这个......
  • SpringBoot启动异常的错误①
    java:无法访问org.springframework.boot.SpringApplication错误的类文件:/D:/maven/repository/org/springframework/boot/spring-boot/3.0.5/spring-boot-3.0.5.jar!/org/springframework/boot/SpringApplication.class类文件具有错误的版本61.0,应为52.0 2023-04......
  • springboot 日志
    <loggername="com.sinoservices.chainwork.bms"level="INFO"/><loggername="org.hibernate.orm.deprecation"level="error"/><loggername="druid"additivity="true"><levelval......
  • 26-springboot-thymeleaf字符串拼接-常量-符号
    Thymeleaf字符串拼接一种是字符串拼接:<spanth:text="'当前是第'+${sex}+'页,共'+${sex}+'页'"></span>另一种更简洁的方式,使用“|”减少了字符串的拼接:<spanth:text="|当前是第${sex}页,共${sex}页|"></span>Thymeleaf可直接使用的常量和符号1、所有......