Skip to content

[BUG] 序列化枚举类如果是负数会直接crash #2531

@stc-W

Description

@stc-W

问题描述

简要描述您碰到的问题。
在序列化枚举类时有负数的情况

环境信息

请填写以下信息:

  • OS信息: [e.g.:Ubuntu 22.04.3 LTS]
  • JDK信息: [e.g.:openjdk 11.0.22 2024-01-16]
  • 版本信息:[e.g.:Fastjson 2.0.49 兼容1.x.x]

重现步骤

Test case

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.annotation.JSONField;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

public class Test242 {

    @Test
    public void testParseObjectWithNegativeEnumValue() {
        String jsonStr = "{\"code\": -1}";
        Mock m = JSON.parseObject(jsonStr, new TypeReference<Mock>() {}, Feature.SupportAutoType);
        assertNotNull(m);
        assertEquals(EnumClass.NEGATIVE_ONE, m.getCode());
    }
}

class Mock {
    @JSONField(name = "code")
    private EnumClass code;

    public EnumClass getCode() {
        return code;
    }

    public void setCode(EnumClass code) {
        this.code = code;
    }
}

enum EnumClass {
    A(1),
    NEGATIVE_ONE(-1);

    private final int code;

    EnumClass(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }

    public static EnumClass valueOf(int code) {
        for (EnumClass enumClass : EnumClass.values()) {
            if (enumClass.getCode() == code) {
                return enumClass;
            }
        }
        return null;
    }
}
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

public class Test243 {

    @Test
    public void testEnumDeserializationWithNegativeValue() {
        String jsonStr = "{\"code\":-1}"; // Updated JSON with a negative code value
        Mock m = JSON.parseObject(jsonStr, Mock.class, Feature.AllowISO8601DateFormat);
        assertNotNull(m);
        assertEquals(-1, m.getCode().getCode()); // Expected to get the code value -1
    }

    static class Mock {
        private EnumClass code;

        public EnumClass getCode() {
            return code;
        }

        public void setCode(EnumClass code) {
            this.code = code;
        }
    }

    enum EnumClass {
        A(1);

        private int code;

        EnumClass(int code) {
            this.code = code;
        }

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }
    }
}
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.junit.Test;

import java.lang.reflect.Type;

public class Test244 {

    @Test
    public void testEnumDeserializationWithNegativeValue() {
        String jsonStr = "{\"code\":-1}";
        Type type = new TypeReference<Mock>(){}.getType();
        Mock m = JSON.parseObject(jsonStr, type);
        assert m != null;
        assert m.getCode().getCode() == -1;
    }
}

class Mock {
    private EnumClass code;

    public EnumClass getCode() {
        return code;
    }

    public void setCode(EnumClass code) {
        this.code = code;
    }
}

enum EnumClass {
    A(1),
    B(-1);

    private int code;

    EnumClass(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }
}
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import org.junit.Test;
import java.nio.charset.StandardCharsets;
import java.nio.charset.CharsetDecoder;
import java.lang.reflect.Type;
import com.alibaba.fastjson.parser.Feature;

public class Test251 {
    @Test
    public void testParseObjectWithNegativeEnumValue() {
        byte[] jsonBytes = "{\"code\": -1}".getBytes(StandardCharsets.UTF_8);
        
        CharsetDecoder charsetDecoder = StandardCharsets.UTF_8.newDecoder();
        Type clazz = Mock.class;
        Feature[] features = new Feature[0];

        Mock m = JSON.parseObject(jsonBytes, 0, jsonBytes.length, charsetDecoder, clazz, features);
        assert m != null;
        assert m.getCode().getCode() == -1;
    }

    class Mock {
        @JSONField(name = "code")
        private EnumClass code;

        Mock() {}

        public EnumClass getCode() {
            return code;
        }

        public void setCode(EnumClass code) {
            this.code = code;
        }
    }

    enum EnumClass {
        A(1);

        private int code;

        EnumClass(int code) {
            this.code = code;
        }

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }
    }
}

期待的正确结果

能够正常序列化

相关日志输出

*com.alibaba.fastjson.JSONException: read field 'Test243$Mock.setCode, offset 11, character }, line 1, column 11, fastjson-version 2.0.49 {"code":-1}

at com.alibaba.fastjson.JSON.parseObject(JSON.java:553)
at Test243.testEnumDeserializationWithNegativeValue(Test243.java:13)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)

Caused by: com.alibaba.fastjson2.JSONException: No enum ordinal Test243.EnumClass.-1
at com.alibaba.fastjson2.reader.ObjectReaderImplEnum.readObject(ObjectReaderImplEnum.java:238)
at com.alibaba.fastjson2.reader.FieldReaderObject.readFieldValue(FieldReaderObject.java:154)
at com.alibaba.fastjson2.reader.ObjectReader1.readObject(ObjectReader1.java:286)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:543)
... 26 more。*

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixed

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions