美文网首页already收藏JavaScript技术
Jackson自定义序列化注解(1)- Map的key驼峰蛇形的

Jackson自定义序列化注解(1)- Map的key驼峰蛇形的

作者: 小胖学编程 | 来源:发表于2022-04-09 08:58 被阅读0次

    需求:完成响应对象驼峰->蛇形的转换,包括响应对应中Map类型的key也需要转换。

    准备工作

    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>31.0.1-jre</version>
    </dependency>
    
    @Data
    public class User {
    
        private String nameInfo;
    
        private String ageInfo;
    
        private Account account;
    
        @JsonSerialize(using = MapNamingStrategySerialize.class)
        private Map<String, Object> extraMap;
    
        @JsonSerialize(using = MapNamingStrategySerialize.class)
        private Map<String, String> cache;
    
        @Data
        public static class Account {
    
            private Long accountId;
    
            @JsonProperty("name_4_user")
            private String name4User;
        }
    
        public static User builder() {
            User user = new User();
            user.setNameInfo("coder");
            user.setAgeInfo("28");
    
            Account account = new Account();
            account.setAccountId(1001L);
            account.setName4User("liming");
            user.setAccount(account);
    
            Map<String, Object> extra = new HashMap<>();
            extra.put("id4User", "123");
            extra.put("userAge", 23);
            extra.put("myPrice", 12.345);
            extra.put("uId", 1200L);
            extra.put("account", account);
            user.setExtraMap(extra);
    
    
            Map<String, String> cache = new HashMap<>();
            cache.put("id4Cache", "123");
            cache.put("name4Cache", "456");
            user.setCache(cache);
            return user;
        }
    }
    

    1. 【存在问题】方式一

    public class Test1 {
    
        public static void main(String[] args) throws JsonProcessingException {
            userStrategy();
        }
    
        /**
         * 使用策略来进行实现
         */
        private static void userStrategy() throws JsonProcessingException {
            User user = User.builder();
            ObjectMapper mapper = new ObjectMapper();
            mapper.setPropertyNamingStrategy(com.fasterxml.jackson.databind.PropertyNamingStrategy.SNAKE_CASE);
            String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);
            System.out.println(json);
        }
    }
    

    这种无法转换Map中的key。

    2. 【可以实现】方式二:JsonSerializer

    public class MapNamingStrategySerialize extends JsonSerializer<Map<String, Object>> {
    
        private static Map<String/*LOWER_CAMEL*/, String/*LOWER_UNDERSCORE*/> NAME_CACHE = new ConcurrentHashMap<>();
    
        @Override
        public void serialize(Map<String, Object> map, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
                throws IOException {
            Map<String, Object> newMap = new HashMap<>();
            //重新设置key
            map.forEach((k, v) -> newMap.put(genKey(k), v));
            //写对象
            jsonGenerator.writeObject(newMap);
        }
    
        private String genKey(String k) {
            String v = NAME_CACHE.get(k);
            if (v != null) {
                return v;
            }
            return NAME_CACHE.computeIfAbsent(k, this::lowerUnderScoreWithNumber);
        }
    
        /**
         * com.google.common.base.CaseFormat 从驼峰转下划线,遇到带数字的会导致问题的错误
         * 具体的问题是,数字后边会加上正确的下划线,但是前边不会,比如
         * id4User 应该转成 id_4_user
         * 但实际会被转成 id4_user
         * <p>
         * 此处转化为蛇形时,数字依旧使用_Number_进行区分。
         */
        private String lowerUnderScoreWithNumber(String key) {
    
            Matcher m = Pattern.compile("(?<=[a-z])[0-9]").matcher(lowerUnderScore(key));
            StringBuffer sb = new StringBuffer();
            while (m.find()) {
                m.appendReplacement(sb, "_" + m.group());
            }
            m.appendTail(sb);
            return sb.toString();
        }
    
        private String lowerUnderScore(String key) {
            return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, key);
        }
    
    }
    

    在Map属性上使用@JsonSerialize(using = MapNamingStrategySerialize.class)即可实现。

    下一篇:Jackson自定义序列化注解(2)- Map扁平化到Bean中(&格式转换)

    相关文章

      网友评论

        本文标题:Jackson自定义序列化注解(1)- Map的key驼峰蛇形的

        本文链接:https://www.haomeiwen.com/subject/zbdqdrtx.html