自定义的枚举类型反序列化
fastjson默认提供的对枚举类型的反序列化的方式有两种
- 根据枚举的name
- 根据枚举的ordinal值
但是如果需要通过自定义的值反序列化成枚举,就需要自定义反序列化器。
如下面枚举,我想通过EnumValue接口返回的value值进行反序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
interface EnumValue{ int value(); } enum TestEnum implements EnumValue{ TEST1(1), TEST2(2), ; private int value; TestEnum(int value){ this.value=value; } @Override public int value() { return value; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
class Bean{ private int id; private TestEnum testEnum; public int getId() { return id; } public void setId(int id) { this.id = id; } public TestEnum getTestEnum() { return testEnum; } public void setTestEnum(TestEnum testEnum) { this.testEnum = testEnum; } @Override public String toString() { return "Bean{" + "id=" + id + ", testEnum=" + testEnum + '}'; } } |
通过下面代码直接序列化,int类型的值会自动用ordinal,ordinal从0开始 ,TestEnum枚举有2个,ordinal值从0-1,这里会发生ArrayIndexOutOfBoundsException
1 2 3 |
String jsonStr = "{\"id\":1,\"testEnum\":2}"; Bean bean = JSON.parseObject(jsonStr, Bean.class); System.out.println(bean); |
解决方法:
自定义反序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
class EnumValueDeserializer implements ObjectDeserializer { @Override public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { final JSONLexer lexer = parser.lexer; final int token = lexer.token(); Class cls = (Class) type; Object[] enumConstants = cls.getEnumConstants(); if (EnumValue.class.isAssignableFrom(cls)) { for (Object enumConstant : enumConstants) { if (((EnumValue) enumConstant).value() == lexer.intValue()) { return (T) enumConstant; } } } else { //没实现EnumValue接口的 默认的按名字或者按ordinal if (token == JSONToken.LITERAL_INT) { int intValue = lexer.intValue(); lexer.nextToken(JSONToken.COMMA); if (intValue < 0 || intValue > enumConstants.length) { throw new JSONException("parse enum " + cls.getName() + " error, value : " + intValue); } return (T) enumConstants[intValue]; } else if (token == JSONToken.LITERAL_STRING) { return (T) Enum.valueOf(cls, lexer.stringVal()); } } return null; } @Override public int getFastMatchToken() { return JSONToken.LITERAL_INT; } } |
注册反序列化器
注册有三种方法
通过ParserConfig注册
1 2 3 4 5 |
String jsonStr = "{\"id\":1,\"testEnum\":2}"; ParserConfig globalInstance = ParserConfig.getGlobalInstance(); globalInstance.putDeserializer((Type) TestEnum.class, new EnumValueDeserializer()); Bean bean = JSON.parseObject(jsonStr, Bean.class); System.out.println(bean); |
通过JSONType注解注册
1 2 |
@JSONType(deserializer = EnumValueDeserializer.class) enum TestEnum implements EnumValue { |
#### 复写ParserConfig,替换掉默认的枚举反序列化器,这种方式是全局的,对所有枚举起作用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class MyParserConfig extends ParserConfig{ @Override public ObjectDeserializer getDeserializer(Class<?> clazz, Type type) { ObjectDeserializer derializer; if (clazz.isEnum()) { Class<?> deserClass = null; JSONType jsonType = clazz.getAnnotation(JSONType.class); if (jsonType != null) { deserClass = jsonType.deserializer(); try { derializer = (ObjectDeserializer) deserClass.newInstance(); this.putDeserializer(type,derializer); return derializer; } catch (Throwable error) { // skip } } //这里替换了原来的反序列化器。 derializer = new EnumValueDeserializer(); return derializer; } return super.getDeserializer(clazz, type); } |
1 2 3 |
String jsonStr = "{\"id\":1,\"testEnum\":2}"; Bean bean = JSON.parseObject(jsonStr,(Type)Bean.class,new MyParserConfig()); System.out.println(bean); |
https://wujiazhen2.github.io/2018/10/27/fastjson%E4%BD%BF%E7%94%A8%E7%BB%8F%E9%AA%8C/