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

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

准备工作


  com.google.guava
  guava
  31.0.1-jre

@Data
public class User {

    private String nameInfo;

    private String ageInfo;

    private Account account;

    @JsonSerialize(using = MapNamingStrategySerialize.class)
    private Map extraMap;

    @JsonSerialize(using = MapNamingStrategySerialize.class)
    private Map 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 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 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> {

    private static Map NAME_CACHE = new ConcurrentHashMap<>();

    @Override
    public void serialize(Map map, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
            throws IOException {
        Map 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
     * 

* 此处转化为蛇形时,数字依旧使用_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驼峰蛇形的转换)