Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] JSON.to或jsonObject.to不执行JSONType中的deserializer指定的自定义反序列法方法 #2726

Closed
yhl452493373 opened this issue Jun 21, 2024 · 2 comments
Assignees
Labels
bug Something isn't working fixed
Milestone

Comments

@yhl452493373
Copy link

yhl452493373 commented Jun 21, 2024

问题描述

简要描述您碰到的问题。
在枚举上增加了@JSONType注解,并指定了反序列化类,但是如果反序列化对象本身是个JSONArray,将其包含的JSONObject转为Bean时,枚举字段不能正常转换,抛出异常(JSONArray整体转换没有测试过,大佬可以顺带一起测试下)。必须先将JSONArray里的JSONObject转为JSON字符串,再调用JSON.to才会执行

环境信息

请填写以下信息:

  • OS信息: macOS 14
  • JDK信息: Oracle 1.8
  • 版本信息:fastjson 2.0.51

重现步骤

如何操作可以重现该问题:

以下代码,testFastJsonEnumDeserializerFailed失败,testFastJsonEnumDeserializerSucceed成功

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.fastjson2.reader.ObjectReader;
import lombok.Getter;
import lombok.Setter;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Type;
import java.util.Objects;

public class FastJsonTest {
    @Getter
    @Setter
    static class Bean {
        private ElementType elementType;
    }

    @JSONType(writeEnumAsJavaBean = true, deserializer = FastJsonEnumDeserializer.class)
    @Getter
    enum ElementType {
        HTML("HTML"),
        DIV("DIV");

        final String name;

        ElementType(String name) {
            this.name = name;
        }
    }

    @SuppressWarnings("rawtypes")
    static class FastJsonEnumDeserializer implements ObjectReader<Object> {
        @Override
        public Object readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
            if (jsonReader.nextIfNull()) {
                return null;
            }
            Class fieldClass = (Class) fieldType;
            Object value = jsonReader.readAny();
            if (fieldClass.isEnum()) {
                Enum[] enumConstants = (Enum[]) fieldClass.getEnumConstants();
                if (value instanceof Integer) {
                    for (Enum enumConstant : enumConstants) {
                        if (Objects.equals(enumConstant.ordinal(), value)) {
                            return enumConstant;
                        }
                    }
                } else {
                    for (Enum enumConstant : enumConstants) {
                        if (Objects.equals(enumConstant.name(), value)) {
                            return enumConstant;
                        }
                    }
                }
            }
            return null;
        }
    }

    @Test
    public void testFastJsonEnumDeserializerFailed() {
        String json = "[{\"elementType\":1}]";
        JSONArray jsonArray = JSONArray.parseArray(json);
        for (Object o : jsonArray) {
            JSONObject jsonObject = (JSONObject) o;
            Bean bean = jsonObject.to(Bean.class);
            System.out.println(bean.elementType);
        }
    }

    @Test
    public void testFastJsonEnumDeserializerSucceed() {
        String json = "[{\"elementType\":1}]";
        JSONArray jsonArray = JSONArray.parseArray(json);
        for (Object o : jsonArray) {
            String jsonString = JSON.toJSONString(o);
            Bean bean = JSON.to(Bean.class, jsonString);
            System.out.println(bean.elementType);
        }
    }
}

期待的正确结果

上述代码中,testFastJsonEnumDeserializerFailed应当成功执行,在控制台输出枚举的名称DIV

相关日志输出

testFastJsonEnumDeserializerFailed的日志:

com.alibaba.fastjson2.JSONException: can not cast to FastJsonTest$ElementType, from class java.lang.Integer

	at com.alibaba.fastjson2.util.TypeUtils.cast(TypeUtils.java:1563)
	at com.alibaba.fastjson2.reader.FieldReader.acceptAny(FieldReader.java:450)
	at com.alibaba.fastjson2.reader.ObjectReaderAdapter.createInstance(ObjectReaderAdapter.java:669)
	at com.alibaba.fastjson2.JSONObject.to(JSONObject.java:1249)
	at FastJsonTest.testFastJsonEnumDeserializerFailed(FastJsonTest.java:69)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
	at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.util.ArrayList.forEach(ArrayList.java:1259)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.util.ArrayList.forEach(ArrayList.java:1259)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
	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)

附加信息

如果你还有其他需要提供的信息,可以在这里填写(可以提供截图、视频等)。

@yhl452493373 yhl452493373 added the bug Something isn't working label Jun 21, 2024
@yhl452493373
Copy link
Author

以上示例代码,elementType用的是枚举的ordinal,实际业务中,是自定义的一些值。

@yanxutao89 yanxutao89 self-assigned this Jun 21, 2024
wenshao pushed a commit that referenced this issue Jun 25, 2024
…2727)

* fix support custom reader for enum, for issue #2688 and issue #2726
@wenshao wenshao added this to the 2.0.52 milestone Jun 25, 2024
@wenshao wenshao added the fixed label Jun 25, 2024
@wenshao
Copy link
Member

wenshao commented Jul 14, 2024

@wenshao wenshao closed this as completed Jul 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fixed
Projects
None yet
Development

No branches or pull requests

3 participants