Jackson自定义序列化注解(1)- Map的key驼峰蛇形的
2022-04-09 本文已影响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)
即可实现。