diff --git a/src/main/java/org/redkale/convert/ConvertEnumValue.java b/src/main/java/org/redkale/convert/ConvertEnumValue.java new file mode 100644 index 000000000..3850c53b9 --- /dev/null +++ b/src/main/java/org/redkale/convert/ConvertEnumValue.java @@ -0,0 +1,28 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package org.redkale.convert; + +import java.lang.annotation.*; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * 用于枚举类序列化的字段名
+ * + * + *

+ * 详情见: https://redkale.org + * + * @author zhangjx + * @since 2.8.0 + */ +@Inherited +@Documented +@Target({TYPE}) +@Retention(RUNTIME) +public @interface ConvertEnumValue { + + String value(); +} diff --git a/src/main/java/org/redkale/convert/ConvertFactory.java b/src/main/java/org/redkale/convert/ConvertFactory.java index 96c982b88..4cd7b4b60 100644 --- a/src/main/java/org/redkale/convert/ConvertFactory.java +++ b/src/main/java/org/redkale/convert/ConvertFactory.java @@ -243,7 +243,7 @@ public abstract class ConvertFactory { public abstract ConvertFactory createChild(boolean tiny); protected SimpledCoder createEnumSimpledCoder(Class enumClass) { - return new EnumSimpledCoder(enumClass); + return new EnumSimpledCoder(this, enumClass); } protected Type formatObjectType(Type type) { diff --git a/src/main/java/org/redkale/convert/ext/EnumSimpledCoder.java b/src/main/java/org/redkale/convert/ext/EnumSimpledCoder.java index 3c8090bb5..3df9ebf7a 100644 --- a/src/main/java/org/redkale/convert/ext/EnumSimpledCoder.java +++ b/src/main/java/org/redkale/convert/ext/EnumSimpledCoder.java @@ -5,9 +5,10 @@ */ package org.redkale.convert.ext; -import org.redkale.convert.Reader; -import org.redkale.convert.SimpledCoder; -import org.redkale.convert.Writer; +import java.lang.reflect.*; +import java.util.*; +import org.redkale.convert.*; +import org.redkale.util.RedkaleClassLoader; /** * 枚举 的SimpledCoder实现 @@ -22,14 +23,50 @@ import org.redkale.convert.Writer; */ public final class EnumSimpledCoder extends SimpledCoder { - public EnumSimpledCoder(Class type) { + private final Encodeable valueEncoder; + + private final Map enumToValues; + + private final Map valueToEnums; + + public EnumSimpledCoder(final ConvertFactory factory, Class type) { this.type = type; + ConvertEnumValue cev = type.getAnnotation(ConvertEnumValue.class); + if (cev == null) { + this.valueEncoder = null; + this.enumToValues = null; + this.valueToEnums = null; + } else { + try { + String fieldName = cev.value(); + Field field = type.getDeclaredField(fieldName); + RedkaleClassLoader.putReflectionField(fieldName, field); + char[] chs = fieldName.toCharArray(); + chs[0] = Character.toUpperCase(chs[0]); + String methodName = "get" + new String(chs); + Method method = type.getMethod(methodName); + RedkaleClassLoader.putReflectionMethod(methodName, method); + Map map1 = new HashMap<>(); + Map map2 = new HashMap<>(); + for (E e : type.getEnumConstants()) { + map1.put(e, method.invoke(e)); + map2.put(method.invoke(e).toString(), e); + } + this.valueEncoder = factory.loadEncoder(field.getType()); + this.enumToValues = map1; + this.valueToEnums = map2; + } catch (Exception e) { + throw new RuntimeException(e); + } + } } @Override public void convertTo(final W out, final E value) { if (value == null) { out.writeNull(); + } else if (valueEncoder != null) { + valueEncoder.convertTo(out, enumToValues.get(value)); } else { out.writeSmallString(value.toString()); } @@ -40,11 +77,16 @@ public final class EnumSimpledCoder) type, value); + if (valueToEnums != null) { + return valueToEnums.get(value); + } else { + return (E) Enum.valueOf((Class) type, value); + } } @Override public Class getType() { return (Class) type; } + } diff --git a/src/test/java/org/redkale/test/convert/EnumBeanTest.java b/src/test/java/org/redkale/test/convert/EnumBeanTest.java new file mode 100644 index 000000000..f920bf263 --- /dev/null +++ b/src/test/java/org/redkale/test/convert/EnumBeanTest.java @@ -0,0 +1,61 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package org.redkale.test.convert; + +import org.redkale.convert.ConvertEnumValue; +import org.junit.jupiter.api.*; +import org.redkale.convert.json.JsonConvert; + +/** + * + * @author zhangjx + */ +public class EnumBeanTest { + + private boolean main; + + public static void main(String[] args) throws Throwable { + EnumBeanTest test = new EnumBeanTest(); + test.main = true; + test.run(); + } + + @Test + public void run() throws Exception { + EnumBean bean = new EnumBean(); + bean.v1 = EnumKey.TWO; + bean.v2 = 5; + String expect = "{\"v1\":2,\"v2\":5}"; + String json = JsonConvert.root().convertTo(bean); + if (!main) Assertions.assertEquals(expect, json); + System.out.println(json); + EnumBean b = JsonConvert.root().convertFrom(EnumBean.class, json); + String js = JsonConvert.root().convertTo(b); + System.out.println(js); + if (!main) Assertions.assertEquals(expect, js); + } + + public static class EnumBean { + + public EnumKey v1; + + public int v2; + } + + @ConvertEnumValue("code") + public static enum EnumKey { + ONE(1), TWO(2); + + private final int code; + + private EnumKey(int v) { + this.code = v; + } + + public int getCode() { + return code; + } + } +}