无法将JSON值反序列化为类型

时间:2018-08-11 01:56:31

标签: java json jackson jersey-2.0 json-deserialization

我试图在我的Web服务中反序列化发布请求,但最终得到HTTP 500提示javax.json.bind.JsonbException: Error deserialize JSON value into type: class [C。我正在使用Jackson来处理JSON内容。

这是我从邮递员发送的JSON字符串:

{"firstName":"FirstName","middleName":"middleName","lastName":"LastName","name":"SomeName","password":"$0meR@nd0m","creationTimeStamp":1533950475466}  

这是我的POJO:

@XmlRootElement
public class UserFormInterceptor   {
    @Pattern(regexp = "^[\\S][\\p{L} .'-]+$") @Size(min = 2, max = 64) @NotEmpty @NotNull
    private String firstName;
    @Pattern(regexp = "^[\\S][\\p{L} .'-]+$") @Size(min = 2, max = 64)
    private String middleName;
    @Pattern(regexp = "^[\\S][\\p{L} .'-]+$") @Size(min = 2, max = 64) @NotEmpty @NotNull
    private String lastName;
    @Pattern(regexp = "^[a-zA-z][\\w]*$") @Size(min = 8, max = 64) @NotEmpty @NotNull
    private String name;
    @Pattern(regexp = "(?=.*?[A-Z]+)(?=.*?[0-9]+)(?=.*?[\\p{Punct}]+).*") @Size(min = 8, max = 64) @NotEmpty @NotNull
    private char[] password;
    @Positive @NotEmpty @NotNull
    private long creationTimeStamp;

    public UserFormInterceptor() {}

    public UserFormInterceptor(@NotNull String name, @NotNull String password, @Positive long creationTimeStamp, @NotNull String firstName, String middleName, @NotNull String lastName) {
        this.name = name;
        this.password = password.toCharArray();
        this.creationTimeStamp = creationTimeStamp;
        this.firstName = firstName;
        this.middleName = middleName;
        this.lastName = lastName;
    }


    @NotNull
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(@NotNull String firstName) {
        this.firstName = firstName;
    }

    public String getMiddleName() {
        return middleName;
    }

    public void setMiddleName(String middleName) {
        this.middleName = middleName;
    }

    @NotNull
    public String getLastName() {
        return lastName;
    }

    public void setLastName(@NotNull String lastName) {
        this.lastName = lastName;
    }

    @NotNull
    public String getName() {
        return name;
    }

    public void setName(@NotNull String name) {
        this.name = name;
    }

    @NotNull
    public char[] getPassword() {
        return password;
    }

    public void setPassword(@NotNull String password) {
        this.password = password.toCharArray();
    }

    public long getCreationTimeStamp() {
        return creationTimeStamp;
    }

    public void setCreationTimeStamp(long creationTimeStamp) {
        this.creationTimeStamp = creationTimeStamp;
    }

    public Map<String, Object> buildMap() {
        Map<String,Object> returnMap = new HashMap<>();
        returnMap.put("name",this.getName());
        returnMap.put("firstName",this.firstName);
        returnMap.put("middleName",this.middleName==null ? "" : this.middleName);
        returnMap.put("lastName",this.lastName);
        returnMap.put("creationTimeStamp",Long.toString(this.getCreationTimeStamp()));
        return returnMap;
    }
}  

这是我的请求处理程序类:

@Path("/users")
public class UserController {
    private static final UserDAO userDao = new UserDAO();

    @POST
    @Path(value = "/signup")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(value = MediaType.APPLICATION_JSON)
    public Response signUpUser(@Valid @NotNull UserFormInterceptor userSignUpForm) {
        UserCreatorModel userCreatorModel = (UserCreatorModel) new UserCreatorModel(userSignUpForm)
                .setUniqueId();
        String response = userDao.addCustomer(userCreatorModel);
        return Response.ok(response).build();
    }
}  

这些是我对Jackson的Maven依赖:

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider -->
        <dependency>
            <groupId>com.fasterxml.jackson.jaxrs</groupId>
            <artifactId>jackson-jaxrs-json-provider</artifactId>
            <version>2.9.6</version>
        </dependency>  

这是堆栈跟踪:

StandardWrapperValve[Controller Servlet]: Servlet.service() for servlet Controller Servlet threw exception
javax.json.bind.JsonbException: Error deserialize JSON value into type: class [C.
    at org.eclipse.yasson.internal.serializer.DeserializerBuilder.build(DeserializerBuilder.java:113)
    at org.eclipse.yasson.internal.serializer.ObjectDeserializer.deserializeNext(ObjectDeserializer.java:161)
    at org.eclipse.yasson.internal.serializer.AbstractContainerDeserializer.deserializeInternal(AbstractContainerDeserializer.java:84)
    at org.eclipse.yasson.internal.serializer.AbstractContainerDeserializer.deserialize(AbstractContainerDeserializer.java:60)
    at org.eclipse.yasson.internal.Unmarshaller.deserializeItem(Unmarshaller.java:57)
    at org.eclipse.yasson.internal.Unmarshaller.deserialize(Unmarshaller.java:50)
    at org.eclipse.yasson.internal.JsonBinding.deserialize(JsonBinding.java:45)
    at org.eclipse.yasson.internal.JsonBinding.fromJson(JsonBinding.java:85)
    at org.glassfish.jersey.jsonb.internal.JsonBindingProvider.readFrom(JsonBindingProvider.java:99)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:257)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:236)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:156)
    at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:73)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:156)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1091)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
    at org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:271)
    at org.glassfish.jersey.server.internal.inject.EntityParamValueParamProvider$EntityValueSupplier.apply(EntityParamValueParamProvider.java:97)
    at org.glassfish.jersey.server.internal.inject.EntityParamValueParamProvider$EntityValueSupplier.apply(EntityParamValueParamProvider.java:80)
    at org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.apply(ParamValueFactoryWithSource.java:74)
    at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:92)
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:133)
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:200)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:103)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:493)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:415)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:104)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:277)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:272)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:268)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:268)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:289)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:256)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:703)
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:416)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:370)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:389)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:342)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:229)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1580)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:258)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:652)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:591)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:371)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:238)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:463)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:168)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:242)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:539)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:593)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:573)
    at java.lang.Thread.run(Thread.java:748)
]]  

我也将Jackson依赖项的jar添加到了应用服务器的lib目录中。 我正在使用GlassFish 5.0和Jersey 2.26。 我做错了什么?该如何解决?

1 个答案:

答案 0 :(得分:3)

提示在错误消息中:

Error deserialize JSON value into type: class [C

[C是对应于char[]的类。

查看您的代码,您将password声明为:

    private char[] password;

将其更改为

    private String password;

这是怎么回事,杰克逊不知道如何将JSON字符串反序列化为char[]


有种流派说您不应该使用Java字符串来保存密码...因为它据说可以使黑客从JVM内核中的非GC字符串中提取密码。倾倒。但是现实是,如果黑客能够以这种方式提取密码,那么他们很可能可以做其他事情来获取密码。此外,相同的密码极有可能在Glassfish框架类和/或JSON反序列化器内部创建的String对象中。在这种情况下,使用char[]最有可能是徒劳的。即使您解决了这些问题,只有尽快覆盖char[]的内容,使用char[]表示密码才更加安全。如果让char[]在仍然保留密码的情况下无法访问,您将回到String问题。