当我在 Spring Boot 中的 POST API 中使用对象列表时出现 ClassCastException

问题描述 投票:0回答:1

我想在 Spring Boot 项目中为 POST 请求创建一个简单的 REST API。对于这个 POST 请求,我需要使用这个有效负载:

[
{
 "name": "John",
 "user_name": "johnny",
 "email": "[email protected]",
 "phone": "0000",
 "id": "435445",
 "tag": "zxcvb"
},
{
 "name": "John",
 "user_name": "johnny",
 "email": "[email protected]",
 "phone": "0000",
 "business": "abcd",
 "data": "qwert"
}
]

我无法更改此有效负载模型,有一个包含 2 个对象的列表,这 2 个对象有 4 个公共字段和不同的字段。

我实现了 RestController:

@RestController
@Slf4j
public class DataController {
    @PostMapping("/data")
    DataResponse createData(@RequestBody List<CompleteRequest> completeRequests) {
        log.info("completeRequests = {}", completeRequests);
        DataResponse response = new DataResponse();
        response.setName(completeRequests.get(0).getName());
        response.setUserName(completeRequests.get(0).getUserName());
        response.setEmail(completeRequests.get(0).getEmail());
        response.setPhone(completeRequests.get(0).getPhone());
        response.setId(((TagRequest) completeRequests.get(0)).getId());
        response.setTag(((TagRequest) completeRequests.get(0)).getTag());
        response.setBusiness(((DataRequest) completeRequests.get(1)).getBusiness());
        response.setData(((DataRequest) completeRequests.get(1)).getData());
        return response;
    }
}

对于 RequestObject,我使用一个超类和 2 个子类,因为列表的 2 个对象中有 4 个公共字段。所以我的有效负载应该是一个包含 2 个不同对象的列表。这是一个好方法还是我应该做其他事情?或者我怎样才能创建一个存储 2 个不同对象的列表。

@Getter
@AllArgsConstructor
public class CompleteRequest {
    @JsonProperty("name")
    private String name = null;

    @JsonProperty("user_name")
    private String userName = null;

    @JsonProperty("email")
    private String email = null;

    @JsonProperty("phone")
    private String phone = null;

    @Override
    public String toString() {
        return "CompleteRequest{" +
                "name='" + name + '\'' +
                ", user_name='" + userName + '\'' +
                ", email='" + email + '\'' +
                ", phone='" + phone + '\'' +
                '}';
    }
}


@Getter
public class TagRequest extends CompleteRequest {
    @JsonProperty("id")
    private String id = null;

    @JsonProperty("tag")
    private String tag = null;

    @Builder
    public TagRequest(String name, String userName, String email, String phone, String id, String tag) {
        super(name, userName, email, phone);
        this.id = id;
        this.tag = tag;
    }

    @Override
    public String toString() {
        return "TagRequest{" +
                "id='" + id + '\'' +
                ", tag='" + tag + '\'' +
                '}' + super.toString();
    }
}


@Getter
public class DataRequest extends CompleteRequest {
    @JsonProperty("business")
    private String business = null;

    @JsonProperty("data")
    private String data = null;

    @Builder
    public DataRequest(String name, String userName, String email, String phone, String business, String data) {
        super(name, userName, email, phone);
        this.business = business;
        this.data = data;
    }

    @Override
    public String toString() {
        return "DataRequest{" +
                "business='" + business + '\'' +
                ", data='" + data + '\'' +
                '}' + super.toString();
    }
}

和响应对象:

@Getter
@Setter
public class DataResponse {
    @JsonProperty("name")
    private String name = null;

    @JsonProperty("user_name")
    private String userName = null;

    @JsonProperty("email")
    private String email = null;

    @JsonProperty("phone")
    private String phone = null;

    @JsonProperty("id")
    private String id = null;

    @JsonProperty("tag")
    private String tag = null;

    @JsonProperty("business")
    private String business = null;

    @JsonProperty("data")
    private String data = null;
}

但是当我尝试发出 POST 请求时,我得到 500:

2023-11-07 20:56:52.139  INFO 14288 --- [nio-8080-exec-1] com.dgs.restserver.api.DataController    : completeRequests = [CompleteRequest{name='John', user_name='johnny', email='johny@g
mail.com', phone='0000'}, CompleteRequest{name='John', user_name='johnny', email='[email protected]', phone='0000'}]
2023-11-07 20:56:52.157 ERROR 14288 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exc
eption [Request processing failed; nested exception is java.lang.ClassCastException: class com.dgs.restserver.pojo.CompleteRequest cannot be cast to class com.dgs.restserver.pojo.TagRe
quest (com.dgs.restserver.pojo.CompleteRequest and com.dgs.restserver.pojo.TagRequest are in unnamed module of loader java.net.URLClassLoader @5ad6cc21)] with root cause

java.lang.ClassCastException: class com.dgs.restserver.pojo.CompleteRequest cannot be cast to class com.dgs.restserver.pojo.TagRequest (com.dgs.restserver.pojo.CompleteRequest and com.
dgs.restserver.pojo.TagRequest are in unnamed module of loader java.net.URLClassLoader @5ad6cc21)
        at com.dgs.restserver.api.DataController.createData(DataController.java:25) ~[classes/:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.1.4.RELEASE.jar
:5.1.4.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.1.4.RELEASE.j
ar:5.1.4.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800) ~[spring-webmvc-5.1.4.RELEASE.jar:5.
1.4.RELEASE]
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE]        
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038) ~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908) ~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:660) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.14.jar:9.0.14]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
        at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
java spring-boot rest post classcastexception
1个回答
-1
投票

发生异常是因为您尝试将 CompleteRequest 强制转换为 TagRequest,而 TagRequest 是 TagRequest 的父类且无法强制转换。

您可以在控制器方法签名中使用 TagRequest。

为每种类型的请求创建单独的“createData”方法可能会更好。

© www.soinside.com 2019 - 2024. All rights reserved.