Java Jersey/JAX-RS客户端使用Jackson将POJO作为实体传递

Java Jersey/JAX-RS客户端使用Jackson将POJO作为实体传递,java,json,jersey,jackson,jax-rs,Java,Json,Jersey,Jackson,Jax Rs,我正在尝试使用/JAX-RS实现RESTful web服务客户端: 我的问题是我不想使用JSON;相反,我希望直接使用我的实体(例如,Fizz)。我想使用自动地在JSON和我的实体之间进行序列化(无需在每个方法中显式地进行转换),但我不知道这是如何可能/可行的。理想情况下,我的saveFizz方法可能如下所示: public Fizz saveFizz(Fizz fizz) { WebResource webResource = client.resource("whatever");

我正在尝试使用/JAX-RS实现RESTful web服务客户端:

我的问题是我不想使用JSON;相反,我希望直接使用我的实体(例如,
Fizz
)。我想使用自动地在JSON和我的实体之间进行序列化(无需在每个方法中显式地进行转换),但我不知道这是如何可能/可行的。理想情况下,我的
saveFizz
方法可能如下所示:

public Fizz saveFizz(Fizz fizz) {
    WebResource webResource = client.resource("whatever");

    ClientResponse response = webResource.accept("application/json").post(fizz);
    if(response.getStatus() != 200) {
        throw new RuntimeException("Errors are bad, mkay?");
    }

    Fizz fizz = response.extractSomehow();

    return fizz;
}
假设我的
Fizz
类已经用正确的Jackson注释(
JsonProperty
等)进行了注释


有什么想法吗?

您可以使用Jackson的ObjectMapper:

final ObjectMapper mapper = new ObjectMapper();
mapper.readValue(response.getEntity(String.class), Fizz.class);
只要对Fizz进行了正确的注释,就可以满足您的需要


还有其他选项,通常涉及实现自定义提供程序。

您可以使用Jackson的ObjectMapper:

final ObjectMapper mapper = new ObjectMapper();
mapper.readValue(response.getEntity(String.class), Fizz.class);
只要对Fizz进行了正确的注释,就可以满足您的需要

还有其他选项,通常包括实现自定义提供程序。

如果包括(假设使用maven)

如果您包括(假设您使用maven)


您使用的是Jersey 1.x,请查看

第一件事:我们需要确保您拥有
jersey json
模块

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>${jersey-version}</version>
</dependency>
服务器编程

public class MyApplication extends PackagesResourceConfig {
    public MyApplication() {
        getFeatures()..put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
    }
}
见其他

客户端配置

ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, 
                               Boolean.TRUE);
Client client = Client.create(clientConfig);
第三件事:我们只需要确保我们的资源方法被正确地注释,并正确地进行客户端调用(以允许发现正确的编写器/读取器)

对于接受JSON的方法,应该使用
@consumered(“application/JSON”)
对其进行注释,如果该方法也生成JSON响应,则还应该使用
@products(“application/JSON”)
对其进行注释。因此,它取决于方法的语义,包括哪些注释,可以是一个,也可以是两个

对于客户机,只要我们必须正确配置,提取Java对象,只需使用Java类型调用
getXxx

public void testGetFizz() {
    // Directly extact
    Fizz fizz = r.path("fizz").accept("application/json").get(Fizz.class);
    System.out.println(fizz);

    // Extract from ClientResponse
    ClientResponse response = r.path("fizz").
                     accept("application/json").get(ClientResponse.class);
    Fizz fizz1 = response.getEntity(Fizz.class);
    System.out.println(fizz1);
}
以下是我在测试中使用的其他代码片段

@Path("/fizz")
public class FizzResource {

    @POST
    @Consumes("application/json")
    public Response postFizz(Fizz fizz) {
        System.out.println("==== Created Fizz ===");
        System.out.println(fizz);
        System.out.println("=====================");
        return Response.created(null).build();
    }

    @GET
    @Produces("application/json")
    public Response getFizz() {
        Fizz fizz = new Fizz(1, "fizz");
        return Response.ok(fizz).build();
    }
}
服务器配置

ResourceConfig resourceConfig = new PackagesResourceConfig("test.json.pojo");
resourceConfig.getFeatures().put(
                       JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
客户端配置

ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, 
                               Boolean.TRUE);
Client client = Client.create(clientConfig);
r = client.resource(Main.BASE_URI);
// r = WebResource

您使用的是Jersey 1.x,请查看

第一件事:我们需要确保您拥有
jersey json
模块

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>${jersey-version}</version>
</dependency>
服务器编程

public class MyApplication extends PackagesResourceConfig {
    public MyApplication() {
        getFeatures()..put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
    }
}
见其他

客户端配置

ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, 
                               Boolean.TRUE);
Client client = Client.create(clientConfig);
第三件事:我们只需要确保我们的资源方法被正确地注释,并正确地进行客户端调用(以允许发现正确的编写器/读取器)

对于接受JSON的方法,应该使用
@consumered(“application/JSON”)
对其进行注释,如果该方法也生成JSON响应,则还应该使用
@products(“application/JSON”)
对其进行注释。因此,它取决于方法的语义,包括哪些注释,可以是一个,也可以是两个

对于客户机,只要我们必须正确配置,提取Java对象,只需使用Java类型调用
getXxx

public void testGetFizz() {
    // Directly extact
    Fizz fizz = r.path("fizz").accept("application/json").get(Fizz.class);
    System.out.println(fizz);

    // Extract from ClientResponse
    ClientResponse response = r.path("fizz").
                     accept("application/json").get(ClientResponse.class);
    Fizz fizz1 = response.getEntity(Fizz.class);
    System.out.println(fizz1);
}
以下是我在测试中使用的其他代码片段

@Path("/fizz")
public class FizzResource {

    @POST
    @Consumes("application/json")
    public Response postFizz(Fizz fizz) {
        System.out.println("==== Created Fizz ===");
        System.out.println(fizz);
        System.out.println("=====================");
        return Response.created(null).build();
    }

    @GET
    @Produces("application/json")
    public Response getFizz() {
        Fizz fizz = new Fizz(1, "fizz");
        return Response.ok(fizz).build();
    }
}
服务器配置

ResourceConfig resourceConfig = new PackagesResourceConfig("test.json.pojo");
resourceConfig.getFeatures().put(
                       JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
客户端配置

ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, 
                               Boolean.TRUE);
Client client = Client.create(clientConfig);
r = client.resource(Main.BASE_URI);
// r = WebResource

谢谢@Calardan(+1)-但这是一个将JSON字符串反序列化为
Fizz
实例的独立片段。这在我上面的实际
saveFizz
方法中是如何工作的?我必须向
webResource
方法传递什么?如何从
响应中提取
嘶嘶声
?再次感谢!您可以通过调用
Response.getEntity(String.class)
获得响应的字符串表示形式。如果您想处理InputStream,您可以使用
Response.getEntityInputStream()
发布Fizz实例,您可以使用以下命令:
ObjectMapper mapper=new ObjectMapper();webResource.accept(“application/json”).post(ClientResponse.class,mapper.writeValueAsString(fizz))
这是对json字符串进行marschalling和解组的一个非常基本的解决方案。正如@peeskillet所示,更高级的解决方案将配置Jersey的客户端API或引入自定义提供程序。挑一个最适合你的。我的解决方案实际上没有什么“定制”。该模块具有内置的提供程序,它已经在其
MessageBodyReader
MessageBodyWriter
中使用了Jackson和ObjectMapper。我的答案只说明了如何配置它使其工作:-)你是对的。您的解决方案不涉及任何“自定义”修改。我指的是在需要时使用自己的序列化提供程序作为替代选项。谢谢@Calardan(+1)-但这是一个将JSON字符串反序列化为
Fizz
实例的独立片段。这在我上面的实际
saveFizz
方法中是如何工作的?我必须向
webResource
方法传递什么?如何从
响应中提取
嘶嘶声
?再次感谢!您可以通过调用
Response.getEntity(String.class)
获得响应的字符串表示形式。如果您想处理InputStream,您可以使用
Response.getEntityInputStream()
发布Fizz实例,您可以使用以下命令:
ObjectMapper mapper=new ObjectMapper();webResource.accept(“application/json”).post(ClientResponse.class,mapper.writeValueAsString(fizz))
这是对json字符串进行marschalling和解组的一个非常基本的解决方案。正如@peeskillet所示,更高级的解决方案将配置Jersey的客户端API或引入自定义提供程序。挑一个最适合你的。我的解决方案实际上没有什么“定制”。该模块具有内置的提供者,该提供者已经在其
MessageBodyReader
MessageBod中使用了Jackson和ObjectMapper