Java枚举值默认是Integer类型的,但是我们经常会用到非数字类型值,例如:字符串。JSON序列化时,通常会使用枚举的序号作为值,FastJSON2可以通过JSONField来实现用名称作为值。
public enum Color{
Red("red"),
Green("green"),
Yellow("yellow"),
Blue("blue");
private String value;
Color(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}
@Data
public class Car{
@JSONField(serializeFeatures = JSONWriter.Feature.WriteEnumsUsingName)
private Color color;
private String mode;
}
如果将JSON反序列化就比较麻烦,例如一下JSON。
{
"color":"yellow",
"mode":"modelY"
}
如果项目中有多个这样的枚举类处理很麻烦。这里做了一个尝试,让枚举类实现EnumWithValue接口,在FastJSON公共配置统一设置序列和反序列化方法。
public interface EnumWithValue <T>{
T getValue();
}
public enum Color implements EnumWithValue<String>{
Red("red"),
Green("green"),
Yellow("yellow"),
Blue("blue");
private String value;
Color(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}
@Data
public class Car{
//这里不需要用JSONField标注
private Color color;
private String mode;
}
这里使用了一个第三方的组件io.github.classgraph,扫描EnumWithValue的实现类,FastJSON2全局配置为每个实现类注册了objectReaderProvider和objectWriterProvider。
-
ClassScanner 对io.github.classgraph进行了简单封装,方便获取EnumWithValue的实现类;注意为了提高扫描的效率,需要限定下扫描包。
-
io.github.classgraph的maven依赖
<dependency>
<groupId>io.github.classgraph</groupId>
<artifactId>classgraph</artifactId>
<version>4.8.177</version>
</dependency>
public class ClassScanner {
private String[] packages;
private ScanResult scanResult;
public ClassScanner packages(String... packages) {
this.packages = packages;
return this;
}
public ClassScanner packages() {
this.packages = new String[]{"com.xxx.bbb"};
return this;
}
public ClassScanner scan() {
this.scanResult = new ClassGraph()
.enableClassInfo()
.acceptPackages(packages)
.scan();
return this;
}
public List<Class<?>> getImplementing(Class<?> mClass) {
if (this.scanResult == null) {
this.scan();
}
ClassInfoList classInfos = scanResult.getClassesImplementing(mClass);
List<Class<?>> list = new ArrayList<>();
for (ClassInfo classInfo : classInfos) {
try {
Class<?> tClass = Class.forName(classInfo.getName());
list.add(tClass);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
return list;
}
public void forEachImplementing(Class<?> mClass, Consumer<Class<?>> consumer) {
List<Class<?>> list = getImplementing(mClass);
for (Class<?> item : list) {
consumer.accept(item);
}
}
public static ClassScanner of() {
return new ClassScanner().packages();
}
public static ClassScanner of(String... packages) {
return new ClassScanner().packages(packages);
}
}
public class FastJSON {
public static final JSONWriter.Featu
re[] WRITE_FEATURES = new JSONWriter.Feature[]{
JSONWriter.Feature.WriteNullStringAsEmpty,
JSONWriter.Feature.WriteNullListAsEmpty,
JSONWriter.Feature.WriteNulls,
JSONWriter.Feature.MapSortField,
JSONWriter.Feature.WriteMapNullValue};
public static long WRITE_FEATURES_MASK = 0L;
static {
WRITE_FEATURES_MASK = 0L;
for (JSONWriter.Feature feature : WRITE_FEATURES) {
WRITE_FEATURES_MASK |= feature.mask;
}
registerEnumValue();
}
public static FastJsonConfig getDefaultFastConfig() {
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setCharset(Charset.forName("utf8"));
fastJsonConfig.setWriterFeatures(WRITE_FEATURES);
return fastJsonConfig;
}
public static <T> T parseObject(String text, Class<T> objectClass) {
return JSON.parseObject(text, objectClass);
}
public static String toJSONString(Object obj) {
return JSON.toJSONString(obj, WRITE_FEATURES);
}
private static void registerEnumValue() {
ObjectReaderProvider objectReaderProvider = JSONFactory.getDefaultObjectReaderProvider();
ObjectWriterProvider objectWriterProvider = JSONFactory.getDefaultObjectWriterProvider();
ClassScanner.of().forEachImplementing(EnumWithValue.class, aClass -> {
objectReaderProvider.registerIfAbsent(aClass, (jsonReader, type, o, l) -> {
EnumWithValue[] items = (EnumWithValue[]) aClass.getEnumConstants();
Object value = jsonReader.readAny();
EnumWithValue matched = Arrays.stream(items).filter(x -> x.getValue().equals(value)).findFirst().orElse(null);
return matched != null ? matched : null;
});
objectWriterProvider.register(aClass, (jsonWriter, object, fieldName, fieldType, features) -> {
EnumWithValue value = (EnumWithValue) object;
jsonWriter.writeAny(value.getValue());
});
});
}
}
这个方案看似有点麻烦,但只需要在定义枚举时,实现EnumWithValue接口即可。
3758

被折叠的 条评论
为什么被折叠?



