我在我的应用程序中遇到一些问题,我发送了一个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),但仍然无法正常工作..我错过了什么?
答案 0 :(得分:2)
为了将JSON转换为Java类型,需要MessageBodyReader
和MessageBodyWriter
实现来进行转换。由于您使用的是JsonObject
GSON类型,因此您可以看到this implementation。但是实现存在问题,因为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();
}
}
}
然后我们只需要在客户端和应用程序中注册它。我正在使用独立测试,您可以在此处查看配置
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();
}
}
这是完整的测试,需要this maven dependency
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
之外什么也不做。在客户端测试中,我将响应作为字符串读取,您可以看到结果与初始请求中发送的结果相同。
答案 1 :(得分:1)
使用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"
},
}
答案 2 :(得分:0)
您是否成功解析了任何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)