当程序尝试反序列化实体流中的对象时出现错误

I am getting an error when the program tries to deserialise an object from the entity stream

我有一个名为 Activity 的实体 class,class 正在反序列化并且工作正常,直到我决定向该实体添加一个 int 类型的 id 字段。该字段的 getter 和 setter 是 public 并且似乎没问题,但是当我 运行 从客户端创建对象的测试时,我得到了这个反序列化错误,如下所示。我正在学习使用 jersey 的 REST 教程。

我已经检查了该字段的 setter 和 getter 的可见性,它们既不是包私有的,也不是私有的。

这是我遇到的错误:

javax.ws.rs.ProcessingException: Error deserializing object from entity stream.

at org.glassfish.jersey.jsonb.internal.JsonBindingProvider.readFrom(JsonBindingProvider.java:77)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:233)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:212)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:132)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1067)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:850)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:784)
at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:297)
at org.glassfish.jersey.client.InboundJaxrsResponse.call(InboundJaxrsResponse.java:91)
at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
at org.glassfish.jersey.internal.Errors.process(Errors.java:205)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:365)
at org.glassfish.jersey.client.InboundJaxrsResponse.runInScopeIfPossible(InboundJaxrsResponse.java:240)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:88)
at tzpl.client.ActivityClient.create(ActivityClient.java:54)
at tzpl.client.ActivityClientTest.testCreate(ActivityClientTest.java:62)
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.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access[=10=]0(ParentRunner.java:50)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Caused by: javax.json.bind.JsonbException: Can't deserialize JSON array into: class tzpl.model.Activity
    at org.eclipse.yasson.internal.serializer.DeserializerBuilder.build(DeserializerBuilder.java:141)
    at org.eclipse.yasson.internal.Unmarshaller.deserializeItem(Unmarshaller.java:60)
    at org.eclipse.yasson.internal.Unmarshaller.deserialize(Unmarshaller.java:51)
    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:75)
    ... 38 more


Process finished with exit code 255

这是 Activity 实体:

package tzpl.model;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement
public class Activity {
private int id;
private String description;

private int duration;

private  boolean worthIt;

private User user;

public Activity(){

}

public Activity (int id, String description, int duration, boolean worthIt){
  this.description = description;
  this.duration = duration;
  this.worthIt = worthIt;
  this.id = id;

}

@XmlElement(name="id")
public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

@XmlElement(name="user")
public User getUser() {
    return user;
}

public void setUser(User user) {
    this.user = user;
}

@XmlElement(name="verdict")
public boolean isWorthIt() {
    return worthIt;
}

public void setWorthIt(boolean worthIt) {
    this.worthIt = worthIt;
}



@XmlElement(name="desc")
public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

@XmlElement(name="time-taken")
public int getDuration() {
    return duration;
}

public void setDuration(int duration) {
    this.duration = duration;
}

}

这是我试图用来获取我的 activity 对象的客户端;


package tzpl.client;

import tzpl.model.Activity;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;

public class ActivityClient {
    private Client client;
public ActivityClient() {
    client = ClientBuilder.newClient();

}

public Activity get(String id) {

    WebTarget target = client.target("http://localhost:8080/myapp" +
            "/activities");

    Response response =
            target.path("activity/" + id).request(MediaType.APPLICATION_JSON).get(Response.class);
    if (response.getStatus() != 200) {
        throw new RuntimeException(response.getStatus() + ": An error was" +
                " encountered on the server.");
    }
    return response.readEntity(Activity.class);
}

public List<Activity> get() {
    WebTarget target = client.target("http://localhost:8080/myapp");
    List<Activity> response =
            target.path("activities/").request(MediaType.APPLICATION_JSON).get(List.class);

    return response;
}

public Activity create(Activity activity) {

    WebTarget target = client.target("http://localhost:8080/myapp" +
            "/activities/");
    Response response =
            target.path("activity").request(MediaType.APPLICATION_JSON).post(Entity.entity(activity, MediaType.APPLICATION_JSON));

    if (response.getStatus() != 200) {
        throw new RuntimeException(response.getStatus() + ": there was an" +
                " error on the server.");
    }
    return response.readEntity(Activity.class);
}

public Activity update(Activity activity) {

    WebTarget target = client.target("http://localhost:8080/myapp" +
            "/activities/");
    Response response =
            target.path("activity/"+activity.getId()).request(MediaType.APPLICATION_JSON).put(Entity.entity(activity, MediaType.APPLICATION_JSON));

    if (response.getStatus() != 200) {
        throw new RuntimeException(response.getStatus() + ": there was " +
                "an" +
                " error on the server.");

    }
    return response.readEntity(Activity.class);
}

}

我正在 运行 在我的客户端测试中测试 testCreate 方法,如下所示:


package tzpl.client;

import org.junit.Test;
import tzpl.model.Activity;
import tzpl.repository.ActivityRepository;
import tzpl.repository.ActivityResourceStub;

import java.util.List;

import static org.junit.Assert.assertNotNull;

public class ActivityClientTest {

    @Test
    public void testPut(){
        ActivityRepository activityRepository = new ActivityResourceStub();
        Activity activity = new Activity(6,"Mountain climbing", 45, true);
        Activity activity2 = activityRepository.listAllActivities().get(2);

        ActivityClient client = new ActivityClient();

        activity2 = client.update(activity2);

        assertNotNull(activity2);
    }

    @Test
    public void testGet(){
        ActivityClient client = new ActivityClient();
        Activity activity = client.get("1");
        System.out.println(activity.getDescription());
        assertNotNull(activity);
    }

    @Test
    public void testGetList(){
        ActivityClient client = new ActivityClient();
        List<Activity> activities = client.get();
        System.out.println(activities);
        assertNotNull(activities);
    }

    @Test (expected=RuntimeException.class)
    public void testGetWithBadRequest(){
        ActivityClient client = new ActivityClient();
        client.get("");

    }

    @Test(expected=RuntimeException.class)
    public void testGetWithNotFound(){
        ActivityClient client = new ActivityClient();
        client.get("777");
    }

    @Test
    public void testCreate(){
        ActivityClient client = new ActivityClient();

        Activity activity = new Activity(7,"Skiing", 20, false);

        activity = client.create(activity);

        assertNotNull(activity);
    }
}

在我什至断言 activity 为空或不存在之前,我从 Activity 客户端收到一个错误,抱怨它无法反序列化传入的 Jason 流。我在 pom.xml 中有以下依赖项。正如下面的 pom 所示,我显然对使用 jason 有依赖性,就像我提到的那样,测试仅在引入 id 字段后才中断。

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>tzpl</groupId>
    <artifactId>com.tzpl</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>com.tzpl</name>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey</groupId>
                <artifactId>jersey-bom</artifactId>
                <version>${jersey.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-grizzly2-http</artifactId>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
        </dependency>

        <!-- uncomment this to get JSON support:-->
         <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-binding</artifactId>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.3.2</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <inherited>true</inherited>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>tzpl.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <properties>
        <jersey.version>2.28</jersey.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

我需要有关如何克服此反序列化错误的帮助。

根本原因很清楚:

Can't deserialize JSON array into: class tzpl.model.Activity

反序列化器看到下一个是数组,但你说它应该是一个Activity对象,所以它不能工作。

   <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-moxy</artifactId>
    </dependency>

更改对此的依赖。它会很好地工作。