Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JAX-RS响应对象将对象字段显示为空值_Java_Json_Web Services_Jax Rs_Jersey 2.0 - Fatal编程技术网

Java JAX-RS响应对象将对象字段显示为空值

Java JAX-RS响应对象将对象字段显示为空值,java,json,web-services,jax-rs,jersey-2.0,Java,Json,Web Services,Jax Rs,Jersey 2.0,第一次在应用程序中实现JAX-RS客户机API,在存储响应数据时,我遇到了一些小问题,响应数据作为JSON作为javabean返回。请参阅下面的代码片段,这些代码片段演示了到目前为止我是如何实现它的 object = client.target(uri).request().post(Entity.entity(requestObject, APPLICATION_JSON), Object.class); 本质上,我希望将从web服务返回的JSON响应存储到我的Javabean中,在这个场景

第一次在应用程序中实现
JAX-RS客户机API
,在存储响应数据时,我遇到了一些小问题,响应数据作为
JSON
作为javabean返回。请参阅下面的代码片段,这些代码片段演示了到目前为止我是如何实现它的

object = client.target(uri).request().post(Entity.entity(requestObject, APPLICATION_JSON), Object.class);
本质上,我希望将从web服务返回的
JSON
响应存储到我的Javabean中,在这个场景中,它被命名为
object
requestObject
显然是我通过web服务发送的数据,我可以确认POST确实成功执行了操作

在上面示例的代码行之后,我有一个简单的:
object.toString()调用以查看当前存储在此
对象中的值。但是,当执行此操作并打印到控制台时,所有
对象
字段都打印为
null
,我不理解这是为什么。我已经用类上方的
@XmlRootElement
注释了我的JavaBean类,尽管它仍然不起作用。我确实在这个类中嵌套了另一个对象作为变量,这可能是它不能正确通过的原因吗

例如,当我通过CLI调用web服务时,JSON返回的对象就是这样的:

"response": {
        "description": "test charge",
        "email": "testing@example.com",
        "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
        }
    }
为什么会发生这种情况

更新[下面的响应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
属于
ResponseObject类的Person对象

@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

所以我能够重现这个问题,经过一点测试,我意识到如果我从正确的角度看问题,问题是非常明显的。我最初是从提供者配置可能有问题的角度来看的。但是经过一个简单的“仅Jackson”测试,只需使用
ObjectMapper
并尝试读取值,结果就变得清晰了。问题在于json格式和类的结构

结构如下

{
  "response": {
    "description": "test charge",
     ..
    "person": {
      "name": "Matthew",
      ..
    }
  }
}
这是你们的课程

public class ResponseObject {
    private String description;
    private Person person;
    ...
}
public class Person {
    private String name;
}
问题是顶级对象只需要一个属性
响应
。但是我们的顶级对象是
ResponseObject
,它没有属性
response
。启用ignore unknown properties时,取消建模成功,因为唯一的属性是
response
,该属性不存在任何属性,因此不会填充任何内容

一个简单的(Json/JAXB友好的)修复方法是创建一个包装器类,其
response
属性的类型为
ResponseObject

public class ResponseWrapper {
    private ResponseObject response;
}
这将允许解组成功

final ResponseWrapper ro = target.request(MediaType.APPLICATION_JSON_TYPE)
            .post(Entity.entity(new ResponseWrapper()
                    , MediaType.APPLICATION_JSON_TYPE), ResponseWrapper.class);

完整测试 响应对象

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  }";
    }
}

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    }";
    }
}
响应包装器

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\": \"testing@example.com\",\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();
    }
}
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();
    }
}
单元测试: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\": \"testing@example.com\",\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();
    }
}
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();
    }
}

您可以向我们展示您的bean类以及如何注释字段吗?另外,您正在使用哪个客户端API?如果是Jersey,则是关于JAXB/Json转换的。@azurefrog,我已经更新了我的问题,以便您可以看到我的JavaBeans类。我使用的是
JAX-RS
,但是这只是为我提供了一组
Jersey
使用的接口类,对吗?请让这个问题“重现”。显示客户端请求的完整代码。显示服务器端资源方法。@peeskillet服务器端源不可用,因为此客户端正在与测试支付网关通信。您能否显示完整的客户端请求代码。我要这些东西的原因是我试图重现这个问题,但我做不到。出于几个原因,1。我必须创建自己的客户端代码,这可能与您的不同,也可能与您的不同。2.我必须创建自己完整的运行时环境(依赖项、jersey版本等),因为您没有提供这些信息。3.我必须创建自己的服务器端方法。您可以尝试通过创建自己的服务器端方法来重现这个问题,我们可以使用这个方法。另一方面,很难说实现
ResponseWrapper
类的效果很好。尽管如此,我仍然不明白为什么需要这样做。非常感谢您的帮助。在绑定术语中,
{}
是一个对象(类)。当我们这样做时,
{“person:{}
,它将是一个具有
person
属性的类,其值是一个对象。因此,如果这是我们要解组的JSON,那么将其解组到
ResponseObject
。但是在您的情况下,JSON有另一个级别。
{“response:{“person”:{}}}
,因此需要有一个类来保存
响应
属性(其值是一个对象)现在才有最终意义。我现在完全理解了,感谢您的广泛帮助。