栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Java进阶营】Jackson自定义序列化注解(2)-Map扁平化到Bean中(&格式转换)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Java进阶营】Jackson自定义序列化注解(2)-Map扁平化到Bean中(&格式转换)

上一篇:[Jackson自定义序列化注解(1)- Map的key驼峰蛇形的转换]中,实现了对Map的key的参数转换,但是总是存在一些骚操作:

如上图所示,这样对象Y就可以动态的选择序列化的字段。

本文主要实现Map对象(A,B)如何扁平化到Bean中?且扁平化的过程中,需要完成驼峰->蛇形的转换。
注:借鉴@JsonProperty的实现思路。

实现代码

引入依赖:


  com.google.guava
  guava
  31.0.1-jre


自定义注解:

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface DynamicCaseFormatFields {

    CaseFormat sourceFormat() default CaseFormat.LOWER_CAMEL;

    CaseFormat format() default CaseFormat.LOWER_CAMEL;

    boolean withNumber() default false;

}

public class DynamicCaseFormatFieldsBeanSerializerModifier extends BeanSerializerModifier {

    @Override
    public List changeProperties(SerializationConfig config, BeanDescription beanDesc,
            List beanProperties) {
        return beanProperties.stream().map(bpw -> {
            DynamicCaseFormatFields
                    annotation = bpw.getAnnotation(DynamicCaseFormatFields.class);
            if (annotation == null || !bpw.getType().isTypeOrSubTypeOf(Map.class)
                    || !bpw.getType().getKeyType().isTypeOrSubTypeOf(String.class)) {
                return bpw;
            }
            return new DynamicCaseFormatFieldsBeanPropertyWriter(bpw, annotation);
        }).collect(Collectors.toList());
    }
}

public class DynamicCaseFormatFieldsBeanPropertyWriter extends BeanPropertyWriter {

    private static final long serialVersionUID = 3802011467106097526L;

    private final transient DynamicCaseFormatFields annotation;

    private static final Set SUPPORT_WITH_NUMBER_FORMAT =
            Sets.newHashSet(CaseFormat.LOWER_UNDERSCORE, CaseFormat.UPPER_UNDERSCORE);

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

    public DynamicCaseFormatFieldsBeanPropertyWriter(BeanPropertyWriter base, DynamicCaseFormatFields annotation) {
        super(base);
        this.annotation = annotation;
    }

    @Override
    public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) {
        try {
            Map map = (Map) this._accessorMethod.invoke(bean);
            for (Map.Entry entry : map.entrySet()) {
                gen.writeFieldName(computeTargetNameIfAbsent(annotation, entry.getKey()));
                gen.writeObject(entry.getValue());
            }
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    private String generateCacheKey(DynamicCaseFormatFields annotation) {

        return String.join("", annotation.format().name(),
                annotation.withNumber() && SUPPORT_WITH_NUMBER_FORMAT.contains(CaseFormat.LOWER_UNDERSCORE) ? "_NUMBER"
                                                                                                            : "");
    }

    private String computeTargetNameIfAbsent(DynamicCaseFormatFields annotation, String fieldName) {
        ConcurrentHashMap map =
                NAME_CACHE.computeIfAbsent(generateCacheKey(annotation), k -> new ConcurrentHashMap<>());

        if (annotation.sourceFormat().equals(annotation.format()) && !SUPPORT_WITH_NUMBER_FORMAT.contains(
                annotation.sourceFormat())) {
            return fieldName;
        }

        return map.computeIfAbsent(fieldName, k -> computeTargetName(annotation, k));
    }

    
    private String computeTargetName(DynamicCaseFormatFields annotation, String fieldName) {
        String key = annotation.sourceFormat().to(annotation.format(), fieldName);
        if (!annotation.withNumber() || !SUPPORT_WITH_NUMBER_FORMAT.contains(annotation.format())) {
            return key;
        }
        //处理属性中带数字的格式
        Matcher m = Pattern.compile("(?<=[a-z])[0-9]").matcher(key);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, "_" + m.group());
        }
        m.appendTail(sb);
        return sb.toString();
    }
}

public class DynamicCaseFormatFieldsModules {

    public static SimpleModule create() {
        return new SimpleModule("dynamicCaseFormatFieldsModule")
                .setSerializerModifier(new DynamicCaseFormatFieldsBeanSerializerModifier());
    }
}

使用方式
@Data
public class User {

    private String nameInfo;

    private String ageInfo;

    private Account account;

    
    @DynamicCaseFormatFields(format = CaseFormat.LOWER_UNDERSCORE)
    private Map extraMap;

    @DynamicCaseFormatFields(format = CaseFormat.LOWER_UNDERSCORE, withNumber = true)
    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;
    }
}

测试代码:

public class TestEx {

    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        Jackson2ObjectMapperBuilder.json()
                //添加自定义注解(动态转换器)
                .modulesToInstall(DynamicCaseFormatFieldsModules.create())
                .configure(objectMapper);
        String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(User.builder());
        System.out.println(json);
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/851842.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号