自定義的枚舉類型反序列化
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/