java JAX-RS 响应对象将对象字段显示为 NULL 值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26675967/
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
JAX-RS Response Object displaying Object fields as NULL values
提问by Maff
First time implementing JAX-RS Client API
in an application and I am having some small problems when it comes to storing the response data, which is returned as JSON
as a Java BEAN. Refer to the following code snippets below which demonstrate how I have implemented it thus far.
第一次JAX-RS Client API
在应用程序中实现,在存储JSON
作为 Java BEAN返回的响应数据时遇到了一些小问题。请参阅下面的以下代码片段,其中演示了我迄今为止是如何实现它的。
object = client.target(uri).request().post(Entity.entity(requestObject, APPLICATION_JSON), Object.class);
Essentially, I would like to store the returned JSON
response from the web service into my Java BEAN, which in this scenario is named object
. requestObject
is obviously the data which I am sending through to the web service, and I can confirm that POST does perform the operation successfully.
本质上,我想JSON
将从 Web 服务返回的响应存储到我的 Java BEAN 中,在这种情况下它被命名为object
. requestObject
显然是我发送到 Web 服务的数据,我可以确认 POST 确实成功执行了操作。
After the line of code from the above example I have a simple: object.toString();
call just to see the values currently stored within this object
. However, when this executes and printed out to the console, all the object
fields are printed out as null
, which I do not understand why. I have annotated my Java BEAN class with the following @XmlRootElement
above the class, although it still does not work. I do have another object nested as a variable in this Class, would that potentially be the reason why it does not correctly come through?
在上面示例中的代码行之后,我有一个简单的:object.toString();
调用只是为了查看当前存储在 this 中的值object
。但是,当它执行并打印到控制台时,所有object
字段都打印为null
,我不明白为什么。我已经在我的 Java BEAN 类@XmlRootElement
上面注释了以下内容,尽管它仍然不起作用。我确实有另一个对象作为变量嵌套在这个类中,这可能是它不能正确通过的原因吗?
As an example, this is what my JSON returned object looks like when I invoke the web service through CLI curl
:
例如,当我通过 CLI 调用 Web 服务时,我的 JSON 返回对象如下所示curl
:
"response": {
"description": "test charge",
"email": "[email protected]",
"ip_address": "192.123.234.546",
"person": {
"name": "Matthew",
"address_line1": "42 Test St",
"address_line2": "",
"address_city": "Sydney",
"address_postcode": "2000",
"address_state": "WA",
"address_country": "Australia",
"primary": null
}
}
Any reasons why this could be happening?
这可能发生的任何原因?
UPDATE[Response Bean Class Below]
更新[下面的响应 Bean 类]
@XmlRootElement(name = "response")
public class ResponseObject {
// Instance Variables
private String description;
private String email;
private String ip_address;
private Person person;
// Standard Getter and Setter Methods below
Person Object which belongs to the ResponseObject Class
属于的人对象 ResponseObject Class
@XmlRootElement
public class Card {
// Instance Variables
private String name;
private String address_line1;
private String address_line2;
private String address_city;
private int address_postcode;
private States address_state;
private String address_country;
private String primary;
// Standard Getter and Setter Methods below
采纳答案by Paul Samsotha
So I was able to reproduce the problem, and after a bit of testing, I realized that the problem was pretty obvious, if I had looked at it from the right perspective. I was originally looking at it from the view that maybe something was wrong with the provider configuration. But after a simple "Hymanson only" test, just using the ObjectMapper
and trying the read the value, it became clear. The problem is with the json format and the structure of the classes.
所以我能够重现这个问题,经过一些测试后,我意识到如果我从正确的角度来看问题是很明显的。我最初是从提供程序配置可能有问题的角度来看它的。但是经过简单的“仅Hyman逊”测试,只需使用ObjectMapper
并尝试读取值,就清楚了。问题在于 json 格式和类的结构。
Here is the structure
这是结构
{
"response": {
"description": "test charge",
..
"person": {
"name": "Matthew",
..
}
}
}
And here are your classes
这是你的课程
public class ResponseObject {
private String description;
private Person person;
...
}
public class Person {
private String name;
}
The problem with this is that the top level object is expecting just a single attribute response
. But our top level object is ResponseObject
, which hasno attribute response
. With the ignore unknown properties on, the unmarhalling succeeds, because the only attribute is response
, for which no attribute exists, so nothing gets populated.
这样做的问题是顶级对象只需要一个属性response
。但是,我们的顶级对象ResponseObject
,它有没有属性response
。启用忽略未知属性后,解组成功,因为唯一的属性是response
,不存在该属性,因此不会填充任何内容。
A simple (Json/JAXB friendly) fix would be to create a wrapper class, with a response
attribute of type ResponseObject
一个简单的(Json/JAXB 友好的)修复是创建一个包装类,具有response
类型的属性ResponseObject
public class ResponseWrapper {
private ResponseObject response;
}
This will allow the unmarshalling to succeed
这将使解组成功
final ResponseWrapper ro = target.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(new ResponseWrapper()
, MediaType.APPLICATION_JSON_TYPE), ResponseWrapper.class);
Complete Test
完成测试
ResponseObject
响应对象
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "response")
public class ResponseObject {
private String description;
private String email;
private String ip_address;
private Person person;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getIp_address() {
return ip_address;
}
public void setIp_address(String ip_address) {
this.ip_address = ip_address;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@Override
public String toString() {
return "ResponseObject{"
+ "\n description=" + description
+ "\n email=" + email
+ "\n ip_address=" + ip_address
+ "\n person=" + person
+ "\n }";
}
}
Person
人
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Person {
// Instance Variables
private String name;
private String address_line1;
private String address_line2;
private String address_city;
private int address_postcode;
private String address_state;
private String address_country;
private String primary;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress_line1() {
return address_line1;
}
public void setAddress_line1(String address_line1) {
this.address_line1 = address_line1;
}
public String getAddress_line2() {
return address_line2;
}
public void setAddress_line2(String address_line2) {
this.address_line2 = address_line2;
}
public String getAddress_city() {
return address_city;
}
public void setAddress_city(String address_city) {
this.address_city = address_city;
}
public int getAddress_postcode() {
return address_postcode;
}
public void setAddress_postcode(int address_postcode) {
this.address_postcode = address_postcode;
}
public String getAddress_state() {
return address_state;
}
public void setAddress_state(String address_state) {
this.address_state = address_state;
}
public String getAddress_country() {
return address_country;
}
public void setAddress_country(String address_country) {
this.address_country = address_country;
}
public String getPrimary() {
return primary;
}
public void setPrimary(String primary) {
this.primary = primary;
}
@Override
public String toString() {
return "Person{"
+ "\n name=" + name
+ "\n address_line1=" + address_line1
+ "\n address_line2=" + address_line2
+ "\n address_city=" + address_city
+ "\n address_postcode=" + address_postcode
+ "\n address_state=" + address_state
+ "\n address_country=" + address_country
+ "\n primary=" + primary
+ "\n }";
}
}
ResponseWrapper
响应包装器
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class ResponseWrapper {
private ResponseObject response;
public ResponseObject getResponse() {
return response;
}
public void setResponse(ResponseObject response) {
this.response = response;
}
@Override
public String toString() {
return "ResponseWrapper{"
+ "\n response=" + response
+ "\n}";
}
}
TestResource
测试资源
package jersey.stackoverflow.jaxrs;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/test")
public class TestResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response getResponse(ResponseObject ro) {
final String json = "{\n"
+ " \"response\": {\n"
+ " \"description\": \"test charge\",\n"
+ " \"email\": \"[email protected]\",\n"
+ " \"ip_address\": \"192.123.234.546\",\n"
+ " \"person\": {\n"
+ " \"name\": \"Matthew\",\n"
+ " \"address_line1\": \"42 Test St\",\n"
+ " \"address_line2\": \"\",\n"
+ " \"address_city\": \"Sydney\",\n"
+ " \"address_postcode\": \"2000\",\n"
+ " \"address_state\": \"WA\",\n"
+ " \"address_country\": \"Australia\",\n"
+ " \"primary\": null\n"
+ " }\n"
+ " }\n"
+ "}";
return Response.created(null).entity(json).build();
}
}
Unit Test: TestTestResource
单元测试:TestTestResource
import jersey.stackoverflow.jaxrs.ResponseWrapper;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.moxy.json.MoxyJsonConfig;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.junit.Test;
public class TestTestResource extends JerseyTest {
@Test
public void testPostReturn() throws Exception {
final WebTarget target = target("test");
final ResponseWrapper ro = target.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(new ResponseWrapper()
, MediaType.APPLICATION_JSON_TYPE), ResponseWrapper.class);
System.out.println(ro);
}
@Override
protected Application configure() {
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
return createApp();
}
@Override
protected void configureClient(ClientConfig config) {
config.register(createMoxyJsonResolver());
}
public static ResourceConfig createApp() {
// package where resource classes are
return new ResourceConfig().
packages("jersey.stackoverflow.jaxrs").
register(createMoxyJsonResolver());
}
public static ContextResolver<MoxyJsonConfig> createMoxyJsonResolver() {
final MoxyJsonConfig moxyJsonConfig = new MoxyJsonConfig();
Map<String, String> namespacePrefixMapper = new HashMap<String, String>(1);
namespacePrefixMapper.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");
moxyJsonConfig.setNamespacePrefixMapper(namespacePrefixMapper).setNamespaceSeparator(':');
return moxyJsonConfig.resolver();
}
}
Dependencies in pom.xml
pom.xml 中的依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>2.13</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.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-bundle</artifactId>
<type>pom</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
</dependencies>
Result: Just using toString
结果:仅使用 toString
ResponseWrapper{
response=ResponseObject{
description=test charge
[email protected]
ip_address=192.123.234.546
person=Person{
name=Matthew
address_line1=42 Test St
address_line2=
address_city=Sydney
address_postcode=2000
address_state=WA
address_country=Australia
primary=null
}
}
}