基于jackson 注解 入参 枚举 反序列化 实操

浪费俩小时写了这个,不多说 直接上代码。


  1. 注解
@Documented
@JacksonAnnotationsInside
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JsonDeserialize(using = EnumJsonDeserializer.class)
public @interface JacksonEnum {
}


  1. 实现类


public class EnumJsonDeserializer<T extends Enum<?> & BuzEnum<?>> extends JsonDeserializer<Object> implements ContextualDeserializer {

    private Class<T> classType;

    public EnumJsonDeserializer() {

    }

    public EnumJsonDeserializer(Class<T> classType) {
        this.classType = classType;

    }

    @SneakyThrows
    @Override
    @SuppressWarnings("unchecked")
    public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) {
        JsonNode treeNode = jsonParser.getCodec().readTree(jsonParser);
        try {
            return BuzEnum.findByCode(this.classType, treeNode.asInt()).orElseThrow(() -> new CustomizerException("参数转换失败"));
        } catch (Exception ex) {
            if (treeNode.isTextual()) {
                return BuzEnum.find(this.classType, e -> treeNode.asText().equals(e.name()))
                        .orElseGet(() ->
                                BuzEnum.findByValue(this.classType, treeNode.asText())
                                        .orElseThrow(() -> new CustomizerException("参数转换失败"))
                        );
            }
        }

        // Node was an empty string
        return null;
    }


    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext deserializationContext, BeanProperty beanProperty) {
        Class<?> targetClass = beanProperty.getType().getRawClass();
        if (targetClass != null) {
            return new EnumJsonDeserializer(targetClass);
        }
        return this;
    }
}

  1. 枚举接口

public interface BuzEnum<T> {
    /**
     * 枚举业务状态值
     *
     * @return
     */
    T getCode();

    /**
     * 枚举业务状态描述
     *
     * @return
     */
    String getValue();
    /**
     * 对比是否和code相等,对比地址,值,value转为string忽略大小写对比,text忽略大小写对比
     *
     * @param c code
     * @return 是否相等
     */
    @SuppressWarnings("all")
    default boolean eq(Object c) {
        if (c == null) {
            return false;
        }
        if (c instanceof Object[]) {
            c = Arrays.asList(c);
        }
        return this == c
                || getCode() == c
                || getCode().equals(c)
                || String.valueOf(getCode()).equalsIgnoreCase(String.valueOf(c))
                || getValue().equalsIgnoreCase(String.valueOf(c)
        );
    }

    /**
     * 从指定的枚举类中查找想要的枚举,并返回一个{@link Optional},如果未找到,则返回一个{@link Optional#empty()}
     *
     * @param type      实现了{@link BuzEnum}的枚举类
     * @param predicate 判断逻辑
     * @param <T>       枚举类型
     * @return 查找到的结果
     */
    static <T extends Enum<?> & BuzEnum<?>> Optional<T> find(Class<T> type, Predicate<T> predicate) {
        if (type.isEnum()) {
            for (T each : type.getEnumConstants()) {
                if (predicate.test(each)) {
                    return Optional.of(each);
                }
            }
        }
        return Optional.empty();
    }

    /**
     * 根据枚举的{@link BuzEnum#getCode()}来查找.
     *
     * @see this#find(Class, Predicate)
     */
    static <T extends Enum<?> & BuzEnum<?>> Optional<T> findByCode(Class<T> type, Object code) {
        return find(type, e -> e.getCode() == code || e.getCode().equals(code) || String.valueOf(e.getCode()).equalsIgnoreCase(String.valueOf(code)));
    }

    /**
     * 根据枚举的{@link BuzEnum#getValue()} ()} 来查找.
     *
     * @see this#find(Class, Predicate)
     */
    static <T extends Enum<?> & BuzEnum<?>> Optional<T> findByValue(Class<T> type, String text) {
        return find(type, e -> e.getValue().equalsIgnoreCase(text));
    }

    /**
     * 根据枚举的{@link BuzEnum#getCode()},{@link BuzEnum#getValue()}来查找.
     *
     * @see this#find(Class, Predicate)
     */
    static <T extends Enum<?> & BuzEnum<?>> Optional<T> find(Class<T> type, Object target) {
        return find(type, v -> v.eq(target));
    }


    static <E extends BuzEnum<?>> Optional<E> of(Class<E> type, Object value) {
        if (type.isEnum()) {
            for (E enumConstant : type.getEnumConstants()) {
                Predicate<E> predicate = e -> e.getCode() == value || e.getCode().equals(value) || String.valueOf(e.getCode()).equalsIgnoreCase(String.valueOf(value));
                if (predicate.test(enumConstant)) {
                    return Optional.of(enumConstant);
                }
            }
        }
        return Optional.empty();
    }
}
  1. 使用方式

image

  1. 能够实现的如下
    image
    image
    image
    image
posted @ 2022-06-28 19:18  空明师兄  阅读(362)  评论(0编辑  收藏  举报