使用jersey在POST中检索JsonObject

我在我的应用程序中遇到一些问题,我发送了一个POST请求,但是我无法检索服务器中的JsonObject,这是要发送的代码:

String quo = "{\"network\": {\"label\": \"new net 111\",\"cidr\": \"10.20.105.0/24\"}}"; GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create(); JsonParser json = new JsonParser(); JsonObject jo = (JsonObject)json.parse(quo); ClientConfig config = new ClientConfig(); Client client = ClientBuilder.newClient(config); WebTarget target = client.target("http://localhost:7999/jersey/rest/network/"+tenant_id); Response oj = target.request().accept(MediaType.APPLICATION_JSON) .header("X-Auth-Token", token) .post(Entity.json(gson.toJson(jo))); 

试图检索:

 @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{tenant_id}") public String createNetwork(@HeaderParam(value = "X-Auth-Token") String authToken, @PathParam(value = "tenant_id") String tenant_id, JsonObject network){ Response response = client.target(NOVA_ENDPOINT+tenant_id) .request(MediaType.APPLICATION_JSON) .header("X-Auth-Token", authToken) .post(Entity.json(gson.toJson(network))); System.out.println("Hello"); String responseJson = response.readEntity(String.class); 

JsonObject网络似乎是空的,实际上它不执行该方法(“Hello is not printed”),我得到的错误是“Invalid request body”(因为我觉得JsonObject是空的)..我的错误是什么码?

好的,我明白这个问题与Json处理有关,比如我正在使用Gson。 这是我改进的代码(简化版)跟随用户的建议,但我仍然有问题..

客户端:

 package openstack; 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.Response; import org.glassfish.grizzly.http.server.HttpServer; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; import org.glassfish.jersey.server.ResourceConfig; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import java.net.URI; public class Post { public static HttpServer startServer() { final ResourceConfig resourceConfig = new ResourceConfig() .packages("openstack") .register(GsonMessageBodyHandler.class); return GrizzlyHttpServerFactory.createHttpServer(URI.create("http://localhost:7999/jersey/rest"), resourceConfig); } public static void main(String[] args) { String quo = "{\"keypair\": {\"name\": \"MyKey\"}}"; HttpServer server = startServer(); Client client = ClientBuilder.newClient(); client.register(GsonMessageBodyHandler.class); GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create(); JsonParser json = new JsonParser(); JsonObject jo = (JsonObject)json.parse(quo); WebTarget target = client.target("http://localhost:7999/jersey/rest/test/prova"); System.out.println(jo); Response oj = target.request().post(Entity.json(jo)); String responseString = oj.readEntity(String.class); System.out.println(responseString); } } 

服务器端:

 package openstack; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @Path("/test") public class Test { GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create(); Parliament parliament = new Parliament(); JsonParser json = new JsonParser(); private final Client client; public Test() { client = ClientBuilder.newClient().register(GsonMessageBodyHandler.class); } @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/prova") public Response mymethod(JsonObject keypairsob){ return Response.ok(keypairsob).build(); } } 

我在我的包中创建了一个GsonMessageBodyHandler.java,下面是用户peeskillet建议的代码。 将jersey-container-grizzly2-http.jar添加到我的web-inf / lib(我不知道如何正确使用Maven),但仍然无法正常工作..我缺少什么?

为了将JSON转换为Java类型,需要MessageBodyReaderMessageBodyWriter实现来进行转换。 由于您使用的是GSON类型的JsonObject ,因此您可以看到此实现 。 但是实现有一个问题,因为readFrom方法不能用Jersey 2编译。这是一个固定版本

 import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @Provider @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public final class GsonMessageBodyHandler implements MessageBodyWriter, MessageBodyReader { private static final String UTF_8 = "UTF-8"; private Gson gson; private Gson getGson() { if (gson == null) { final GsonBuilder gsonBuilder = new GsonBuilder(); gson = gsonBuilder.create(); } return gson; } @Override public boolean isReadable(Class type, Type genericType, java.lang.annotation.Annotation[] annotations, MediaType mediaType) { return true; } @Override public Object readFrom(Class type, Type type1, Annotation[] antns, MediaType mt, MultivaluedMap mm, InputStream in) throws IOException, WebApplicationException { InputStreamReader streamReader = new InputStreamReader(in, UTF_8); try { Type jsonType; if (type.equals(type1)) { jsonType = type; } else { jsonType = type1; } return getGson().fromJson(streamReader, jsonType); } finally { streamReader.close(); } } @Override public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return true; } @Override public long getSize(Object object, Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return -1; } @Override public void writeTo(Object object, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { OutputStreamWriter writer = new OutputStreamWriter(entityStream, UTF_8); try { Type jsonType; if (type.equals(genericType)) { jsonType = type; } else { jsonType = genericType; } getGson().toJson(object, jsonType, writer); } finally { writer.close(); } } } 

然后我们只需要在客户端和应用程序中注册它。 我正在使用独立测试,您可以在此处查看配置

 final ResourceConfig resourceConfig = new ResourceConfig() .packages("jersey.stackoverflow.standalone") .register(GsonMessageBodyHandler.class); ... Client c = ClientBuilder.newClient(); c.register(GsonMessageBodyHandler.class); 

这是我用于测试的资源类

 import com.google.gson.JsonObject; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import jersey.stackoverflow.standalone.provider.GsonMessageBodyHandler; @Path("/gson") public class GsonResource { private final Client client; private static final String BASE_URI = "http://localhost:8080/api/gson"; public GsonResource() { client = ClientBuilder.newClient().register(GsonMessageBodyHandler.class); } @POST @Path("/proxy") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response proxyPost(JsonObject json) { Response response = client.target(BASE_URI) .path("main-resource").request().post(Entity.json(json)); JsonObject fromMainResource = response.readEntity(JsonObject.class); return Response.created(null /* should be a created URI */) .entity(fromMainResource).build(); } @POST @Path("/main-resource") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response mainResource(JsonObject json) { return Response.ok(json).build(); } } 

这是完整的测试,需要这种maven依赖

 import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import java.net.URI; 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.Response; import static jersey.stackoverflow.standalone.Main.BASE_URI; import jersey.stackoverflow.standalone.provider.GsonMessageBodyHandler; import org.glassfish.grizzly.http.server.HttpServer; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; import org.glassfish.jersey.server.ResourceConfig; import org.junit.Test; public class GsonProviderTest { public static HttpServer startServer() { final ResourceConfig resourceConfig = new ResourceConfig() .packages("jersey.stackoverflow.standalone") .register(GsonMessageBodyHandler.class); return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), resourceConfig); } public static Client getClient() { Client c = ClientBuilder.newClient(); c.register(GsonMessageBodyHandler.class); return c; } @Test public void testGetIt() { HttpServer server = startServer(); Client c = getClient(); c.register(GsonMessageBodyHandler.class); String quo = "{\"network\": {\"label\": \"new net 111\",\"cidr\": \"10.20.105.0/24\"}}"; GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create(); JsonParser json = new JsonParser(); JsonObject jo = (JsonObject) json.parse(quo); WebTarget target = c.target("http://localhost:8080/api/gson/proxy"); Response response = target.request().post(Entity.json(jo)); String responseString = response.readEntity(String.class); System.out.println(responseString); response.close(); c.close(); server.stop(); } } 

所有的测试都是发送JsonObject 。 虽然没有任何可见的转换为JSON,但在我的任何代码中,它都是由GsonMessageBodyHandler在幕后发生的。 如果查看GsonResource类,可以看到方法除了发送JsonObject什么都不做。 在客户端测试中,我将响应作为String读取,您可以看到结果与初始请求中发送的结果相同。

  • 了解有关MessageBodyReaders和MessageBodyWriters的更多信息

有一种使用post请求在com.google.gson.JsonObject类型中获取JsonObject的简单方法。

我假设已经添加了com.google.gson,jersey和jax-rs的所有依赖项。

在服务器端,您需要具有类似于下面的代码:

 import com.google.gson.JsonObject; import com.google.gson.JsonParser; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Response; @Path("/api") public class JersyAPI { private JsonParser parser= new JsonParser(); @POST @Path("/pudding") @Consumes("application/json") public Response postTest(String requestBody){ Response re = Response.status(200).build(); try{ JsonObject inputObjectJson = parser.parse(requestBody).getAsJsonObject(); 

上面的代码有一个用path / api / pudding定义的rest端点,它接受Request Body as String。 在服务器端收到Json作为字符串后,可以使用com.google.gson.JsonParser将其直接转换为com.google.gson.JsonObject,这可以在您的程序中使用。

要在服务器端发出请求,您发布的请求应如下所示:

 POST /rest/api/pudding HTTP/1.1 Host: localhost:8082 Content-Type: application/json Cache-Control: no-cache Postman-Token: c2b087d9-4830-c8a8-2a19-78273a73898c { "id": 1312312, "name": "Test", "data": { "test" : "data" }, } 

您是否已成功解析任何JSON请求? 可能需要在Jersey中启用JSON支持:

https://jersey.java.net/documentation/1.18/json.html

否则,它可能只是在您的请求上失败,将消息体转换为JsonObject:

 public String createNetwork( @HeaderParam(value = "X-Auth-Token") String authToken, @PathParam(value = "tenant_id") String tenant_id, JsonObject network)