java 使用球衣在 POST 中检索 JsonObject
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27188753/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
retrieve JsonObject in POST with jersey
提问by rok
I have some problems in my application, I send a POST request, but I cannot retrieve the JsonObject in my server, this is the code to send:
我的应用程序有一些问题,我发送了一个 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)));
Trying to retrieve with:
尝试检索:
@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 network seems to be empty, in fact it doesn't execute the method ("Hello is not printed"), the error I get is "Invalid request body" (because the JsonObject is empty I think).. What's wrong with my code?
JsonObject 网络似乎是空的,实际上它并没有执行该方法(“Hello is not print”),我得到的错误是“Invalid request body”(因为我认为 JsonObject 是空的)..我的有什么问题代码?
Ok, I understood that the problem is related to Json handling such as I'm using Gson. This is my improved code (simplified version) following users suggestion, but I still have problems..
好的,我知道问题与 Json 处理有关,例如我使用的是 Gson。这是我根据用户建议改进的代码(简化版),但我仍然有问题..
Client Side:
客户端:
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);
}
}
Server Side:
服务器端:
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();
}
}
I created a GsonMessageBodyHandler.java in my package with the code suggested below by the user peeskillet. Added jersey-container-grizzly2-http.jar to my web-inf/lib (I don't know how to proper use Maven), but still doesn't work.. what am I missing?
我使用用户 peeskillet 在下面建议的代码在我的包中创建了一个 GsonMessageBodyHandler.java。将 jersey-container-grizzly2-http.jar 添加到我的 web-inf/lib(我不知道如何正确使用 Maven),但仍然不起作用..我错过了什么?
回答by Paul Samsotha
In order to convert JSON to a Java type, there is need to for a MessageBodyReader
and a MessageBodyWriter
implementation to do the conversion to and from. Since you are using JsonObject
which is a GSON type, you can see this implementation. There is a problem with the implementation though, as the readFrom
method doesn't compile with Jersey 2. Here is the a fixed version
为了将 JSON 转换为 Java 类型,需要 for aMessageBodyReader
和MessageBodyWriter
implementation 来进行转换。由于您使用的JsonObject
是 GSON 类型,因此您可以看到此实现。但是,实现存在问题,因为该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<Object>,
MessageBodyReader<Object> {
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<Object> type, Type type1, Annotation[] antns,
MediaType mt, MultivaluedMap<String, String> 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<String, Object> 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();
}
}
}
Then we just need to register it with both the client and the application. I'm using a standalone test, where you can see the configuration here
然后我们只需要在客户端和应用程序中注册它。我正在使用独立测试,您可以在此处查看配置
final ResourceConfig resourceConfig = new ResourceConfig()
.packages("jersey.stackoverflow.standalone")
.register(GsonMessageBodyHandler.class);
...
Client c = ClientBuilder.newClient();
c.register(GsonMessageBodyHandler.class);
Here is the resource class I used for the test
这是我用于测试的资源类
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();
}
}
Here's the complete test, which requires this maven dependency
这是完整的测试,它需要这个 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();
}
}
All the test does is send the JsonObject
. Though there isn't any visible conversion to JSON, in any of my code, it is happening behind the scenes by the GsonMessageBodyHandler
. If you look at the GsonResource
class, you can see the methods don't do anything but send out the JsonObject
. In the client test, I read the response as a String, and you can see the result the same as what sent out in the initial request.
测试所做的只是发送JsonObject
. 虽然没有任何可见的 JSON 转换,但在我的任何代码中,它都是由GsonMessageBodyHandler
. 如果您查看GsonResource
该类,您会发现这些方法除了发送JsonObject
. 在客户端测试中,我将响应作为字符串读取,您可以看到与初始请求中发送的结果相同的结果。
回答by ASHISH DHIMAN
There's a simple way to get the JsonObject in com.google.gson.JsonObject type using a post request.
有一种使用 post 请求获取 com.google.gson.JsonObject 类型中的 JsonObject 的简单方法。
I am assuming that all the dependencies for com.google.gson , jersey and jax-rs are already added.
我假设已经添加了 com.google.gson 、 jersey 和 jax-rs 的所有依赖项。
On the server side you need to have code similar to below :
在服务器端,您需要具有类似于以下的代码:
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();
The code above has a rest endpoint defined with path /api/pudding and it is accepting the Request Body as String. Once you receive the Json as string on server side, com.google.gson.JsonParser can be used to convert it into the com.google.gson.JsonObject directly and this can be used in your program.
上面的代码有一个用路径 /api/pudding 定义的休息端点,它接受请求正文作为字符串。在服务器端收到 Json 作为字符串后,可以使用 com.google.gson.JsonParser 将其直接转换为 com.google.gson.JsonObject,这可以在您的程序中使用。
To make a request on server side you post request should look like this :
要在服务器端发出请求,您发布的请求应如下所示:
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"
},
}
回答by user384842
Have you had any JSON requests successfully parsed? It could be that you need to enable JSON support in Jersey:
您是否成功解析了任何 JSON 请求?可能是您需要在 Jersey 中启用 JSON 支持:
https://jersey.java.net/documentation/1.18/json.html
https://jersey.java.net/documentation/1.18/json.html
Otherwise, it may simply be failing on your request to turn the message body into a JsonObject here:
否则,它可能只是无法满足您在此处将消息正文转换为 JsonObject 的请求:
public String createNetwork(
@HeaderParam(value = "X-Auth-Token") String authToken,
@PathParam(value = "tenant_id") String tenant_id,
JsonObject network)