Spring Resttemplate:使用@JsonIgnore 解析导致值为空
Posted
技术标签:
【中文标题】Spring Resttemplate:使用@JsonIgnore 解析导致值为空【英文标题】:Spring Resttemplate: Parsing using @JsonIgnore causes values to be null 【发布时间】:2017-11-09 00:30:05 【问题描述】:所以,我正在使用 Spring Boot 1.5.3 并尝试使用以下 Json 的一部分 - 即 AccountId
和 Username
- (实际上,它是从 SAP Netweaver 实例获取的 oData v2 接口)使用 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),所以我尝试使用上述方法使用ResponseEntity<String>
看看什么我只是将响应解析为字符串表示形式。这样,我可以确保正确返回上面的 json,它就是这样。所以,这些值肯定存在,它必须是解析的问题,但遗憾的是我没有解决这个问题。
希望你能帮帮我!
编辑:正如一个答案提到的,getForObject 可能有效,但这会给我带来其他问题,因为我必须使用基本身份验证,所以它不是真的可行。我还尝试了大小写问题,命名变量 accountID 或 AccountID ,但没有成功。
【问题讨论】:
我的猜测是,问题是 JSON 中包含 AccountId 和 Username 的对象“d”。这实际上将转换为一个名为“d”的类,其中包含字符串“AccountId”和“Username”。出于测试目的,请尝试将您的类命名为“d”而不是 PortalAccount。 另外,在 PortalAccount 类上尝试@JsonTypeName("d") 所以,是的,getBody() 包含我添加到问题中的 json。现在我尝试将类更改为“d”,这会导致相同的行为。另外,我尝试将 JsonTypeName("d") 添加到d
-Class 和重新重构的 PortalAccount-Class 中,但没有成功:/
好的,所以我可能弄错了,您必须将“d”包装在另一个类中,以便您拥有一个包含“d”类型作为属性的类,就像现在一样。同样,出于测试目的。
【参考方案1】:
因此,Christian Zieglers 的评论和回答部分正确。
您需要确保可以从检索到的 Json 映射您的类结构。
所以,为了让它工作,最简单的方法是,而不是创建一个包装对象:
删除您的 @JsonIgnoreProperties
注释。我们将使用对象映射器来做到这一点。
然后,将 Jacksons @JsonRootName 属性添加到您的类 PortalAccount 并将值设置为 d
。你的班级现在应该只有一个注解:
@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)设置为 Unwrap 您的 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】:问题是,根据您的 JSON,ObjectMapper 需要一个包含“d”类型属性的类,该属性包含两个名为“AccountId”和“Username”的属性。
所以,你基本上只需要解析对象“d”的内容。
Parsing a subset of JSON in Java using Jackson 描述了它是如何完成的。
【讨论】:
感谢您的帮助!我认为我们在这里走对了路。刚刚接受了另一个答案,因为它有一个完整的示例,并且恕我直言,使用JsonRootName
比创建包装类更优雅。
确实如此。我不知道@JsonRootName。非常好!【参考方案3】:
您可以尝试使用 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());
【讨论】:
很遗憾我不能,因为我需要基本身份验证,这让我遇到了其他问题。 (老实说,我还没有找到一个使用 get/postforobject 和 basi auth 的工作示例)。以上是关于Spring Resttemplate:使用@JsonIgnore 解析导致值为空的主要内容,如果未能解决你的问题,请参考以下文章