fastjson自定義枚舉反序列化

自定義的枚舉類型反序列化
fastjson默認提供的對枚舉類型的反序列化的方式有兩種

  1. 根據枚舉的name
  2. 根據枚舉的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/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章