Spring Resttemplate:使用@JsonIgnore进行解析会导致值为null

时间:2017-06-07 15:00:56

标签: java json spring-boot jackson resttemplate

所以,我正在使用Spring Boot 1.5.3并尝试使用以下Json的一部分 - 即AccountIdUsername - (实际上,它是一个oData v2接口来自一个SAP Netweaver实例)使用restTemplate.exchange进入类:

{  
   "d":{  
      "__metadata":{  
         "id":"...",
         "uri":"...",
         "type":"...."
      },
      "AccountID":"0100000001",
      "Username":"test@test.com",
      "Partners":{  
         "__deferred":{  
            "uri":"Navigationproperty"
         }
      }
   }
}

我的课程设置如下,因为一开始我只想获取帐户ID和姓名:

@JsonIgnoreProperties(ignoreUnknown = true)
public class PortalAccount implements Serializable{

    public PortalAccount() {
    }

    @JsonProperty("AccountID")
    public String accountID;

    @JsonProperty("Username")
    public String username;

    public String getPortalAccountID() {
        return accountID;
    }

    public void setPortalAccountID(String portalAccountID) {
        this.accountID = portalAccountID;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "Account{" +
                "accountID='" + accountID + '\'' +
                ", username='" + username +'\'' +
                '}';
    }
}

这就是我尝试调用它的方式:

        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = this.createHeaders();
        ResponseEntity<String> response;
        response  = restTemplate.exchange(uri,HttpMethod.GET,new HttpEntity<Object>(httpHeaders),String.class);
        ObjectMapper mapper = new ObjectMapper();

        PortalAccount acc = mapper.readValue(response.getBody(), PortalAccount.class);

我首先尝试直接解析它,就像在使用ResponseEntity<PortalAccount>的文档中一样,但这只会导致一个空类(accountid = null,username = null),所以我尝试使用{{1}上面的方法只是将响应解析为字符串表示时,看看我得到了什么。这样,我可以确保上面的json被正确返回,这就是它。所以,值肯定存在,它必须是解析的问题,但遗憾的是我没有解决这个问题。

我希望你能在这里帮助我!

编辑:正如一个答案所提到的,getForObject可能会起作用,但这导致我遇到其他问题,因为我必须使用基本身份验证,因此它不可行。我也尝试了套管问题,命名变量accountID或AccountID ,但没有成功。

3 个答案:

答案 0 :(得分:2)

问题是,根据你的JSON,ObjectMapper需要一个包含“d”类型属性的类,它包含两个名为“AccountId”和“Username”的属性。

因此,您基本上只需要解析对象“d”的内容。

Parsing a subset of JSON in Java using Jackson描述了它是如何完成的。

答案 1 :(得分:2)

因此,Christian Zieglers的评论和答案是部分正确的。

您需要确保可以从检索到的Json中映射您的类结构。

所以,为了使它工作,最简单的方法是,而不是创建一个包装器对象:

  1. 删除@JsonIgnoreProperties注释。我们将使用对象映射器执行此操作。

  2. 然后,将Jacksons @JsonRootName属性添加到您的类PortalAccount,并将值设置为d。你的班级现在应该只有这一个注释:

  3. 像这样的

    @JsonRootName(value = "d")

    @JsonRootName(value = "d")
    public class PortalAccount implements Serializable{
        public PortalAccount() {
        }
    
        @JsonProperty("AccountID")
        public String accountID;
    
        @JsonProperty("Username")
        public String username;
    
        ...
    }
    

    现在,当你调用它时,你必须设置你的Objectmapper(假设jackson 2)来解开你的rootElement(以及忽略未知属性),如下所示:

    objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    

    所以你的整个电话会是这样的:

    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders httpHeaders = this.createHeaders();
    ResponseEntity<String> response;
    response  = restTemplate.exchange(uri,HttpMethod.GET,new HttpEntity<Object>(httpHeaders),String.class);
    ObjectMapper mapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    
    PortalAccount acc = mapper.readValue(response.getBody(), PortalAccount.class);
    

    重要的是,如上所述,@ JsonRootName属性,因为没有它,UNWRAP_ROOT_VALUE功能将无效。

    希望这有帮助!

答案 2 :(得分:0)

您可以尝试使用getForObject方法代替交换。

以下是一个例子:

@JsonIgnoreProperties(ignoreUnknown = true) 

public class Page { 

    private String name; 
    private String about; 
    private String phone; 
    private String website; 

    public String getName() { 
        return name; 
    } 

    public String getAbout() { 
        return about; 
    } 

    public String getPhone() { 
        return phone; 
    } 

    public String getWebsite() { 
        return website; 
    } 

}  


RestTemplate restTemplate = new RestTemplate();
Page page = restTemplate.getForObject("http://graph.facebook.com/pivotalsoftware", Page.class);
System.out.println("Name:    " + page.getName());
System.out.println("About:   " + page.getAbout());
System.out.println("Phone:   " + page.getPhone());
System.out.println("Website: " + page.getWebsite());