[英]Jackson, howto deserialize fields with custom name?
我嘗試將REST API中的Jira問題反序列化為一個對象。 那很簡單。 我在奮斗的地方是將Jira中的自定義字段映射到屬性上。 我嘗試使用自定義反序列化器,但不會“踢進”。
這就是來自REST調用的Json的樣子:(剝離了某些部分)
{
"expand": "renderedFields,names,schema,...",
"id": "53899",
"key": "DPT-12",
"fields": {
"issuetype": {
"id": "10001",
"name": "Story",
"subtask": false
},
"timespent": null,
"project": {
"id": "10823",
"key": "DPT"
},
"fixVersions": [],
"customfield_10111": null,
"aggregatetimespent": null,
"resolution": null,
"customfield_10112": null,
"customfield_10700": [
"entwicklung-w"
],
"customfield_10304": null,
"resolutiondate": null,
"lastViewed": "2017-04-04T14:34:19.868+0200",
"created": "2017-02-02T12:01:31.443+0100",
"priority": {
"name": "Schwer",
"id": "10001"
},
"assignee": {
"displayName": "me :-)"
},
"updated": "2017-04-04T14:34:19.710+0200",
"status": {
"iconUrl": "https://jira.mobi.ch/",
"name": "Backlog",
"statusCategory": {
"name": "Aufgaben"
}
},
"summary": "Ereignisse in rocket Chat schreiben",
"creator": {
"displayName": "me :-)"
},
"reporter": {
"displayName": "me :-)"
}
}
}
自定義字段名稱是在我的應用程序中配置的(“ customfield_10700”),我想將其映射到屬性上:
private Set<String> deploymentEnvironments;
因此,這里是相關的Dto和測試類(此處刪除了getter和setter)。
測試:
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.hamcrest.collection.IsEmptyCollection.empty;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Set;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.junit.Test;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class IssueFieldsWithDeserializerTest {
@Test
public void testJiraResponseDeserializer() throws IOException, URISyntaxException {
// arrange
String deploymentEnvsKey = "customfield_10700";
String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("jira-example-issue-with-customfield-poc.json").toURI())));
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
SimpleModule module = new SimpleModule();
module.addDeserializer(Set.class, new CustomFieldDeserializer(deploymentEnvsKey));
mapper.registerModule(module);
// act
IssueResponsePoc issue = mapper.readValue(json, IssueResponsePoc.class);
// assert
assertThat("issue is not null", issue, is(not(nullValue())));
assertThat("fields are not null", issue.getFields(), is(not(nullValue())));
assertThat("custom field is not null", issue.getFields().getDeploymentEnvironments(), is(not(nullValue())));
assertThat("custom field is not empty", issue.getFields().getDeploymentEnvironments(), is(not(empty())));
assertThat("custom field has one value", issue.getFields().getDeploymentEnvironments(), hasSize(1));
}
}
IssueResponsePoc類:
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonProperty;
public class IssueResponsePoc implements Serializable {
@JsonProperty private String id;
@JsonProperty private String key;
@JsonProperty private IssueFieldsPoc fields;
}
有趣的類:IssueFieldsPoc
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Set;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.annotation.JsonProperty;
public class IssueFieldsPoc implements Serializable {
@JsonProperty private String summary;
@JsonProperty private IssueType issuetype;
@JsonProperty private IssueUser creator;
@JsonProperty private Date created;
@JsonProperty private IssueUser reporter;
@JsonProperty private IssuePriority priority;
@JsonProperty private IssueResolution resolution;
@JsonProperty private List<String> labels;
@JsonProperty private Date resolutiondate;
@JsonProperty private IssueUser assignee;
@JsonProperty private Date updated;
@JsonProperty private IssueStatus status;
@JsonDeserialize private Set<String> deploymentEnvironments;
// @JsonDeserialize(using = CustomFieldDeserializer.class) private Set<String> deploymentEnvironments;
public Set<String> getDeploymentEnvironments() {
return deploymentEnvironments;
}
public void setDeploymentEnvironments(Set<String> deploymentEnvironments) {
this.deploymentEnvironments = deploymentEnvironments;
}
}
我的反序列化器:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
public class CustomFieldDeserializer extends StdDeserializer<Set<String>> {
private final String customFieldName;
public CustomFieldDeserializer(String customFieldName) {
super((Class<?>) null);
this.customFieldName = customFieldName;
}
@Override
public Set<String> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
System.out.println("deserializer started!");
return null;
}
@Override
public Collection<Object> getKnownPropertyNames() {
return Collections.singletonList(customFieldName);
}
}
我嘗試注冊自定義解串器,但無法啟動,我懷疑它已被忽略,因為傑克遜無法識別字段名稱。 添加“ getKnownPropertyNames”方法無濟於事。 由於我需要將jira自定義字段名稱(我從配置中讀取)放在某個地方,因此我嘗試將其放入反序列化器中。 使用傑克遜注釋@JsonDeserialize。
我還嘗試將其包裝到另一個類中,而不是直接使用Set進行更強的鍵入。 也沒有運氣。
我還嘗試在批注中配置解串器,但是這需要默認的構造函數,而且我無法再配置jira自定義字段名稱。
當前解決方案使用@JsonAnySetter批注:
@JsonAnySetter
public void setCustomProperty(String name, Object value) {
if(StringUtils.startsWith(name, "customfield_")) {
this.customFields.put(name, value);
}
}
但是我更希望在反序列化器中具有這種邏輯。
有什么方法可以幫助傑克遜何時為該動態屬性名稱啟動反序列化器(因為它知道屬性名稱)?
更新:將模塊注冊到映射器。 如答案中所建議,在字段中添加確切的屬性名稱:
@JsonProperty("customfield_10700")
@JsonDeserialize
private Set<String> deploymentEnvironments;
將允許解串器啟動。 但是如上所述,這是一個可配置的值,我不能直接在映射代碼中輸入(或不想輸入)。
好吧,如果我理解正確,則需要將json轉換為java對象。
如果要讓該類忽略未知屬性,則需要在必須忽略的類中添加@JsonIgnoreProperties(ignoreUnknown = true)
( IssueResponsePoc
或IssueFieldsPoc
)。
在@JsonProperty(value = <name_of_property_in_json>)
您可以為Java類中的字段使用任何名稱。
如果您通過帶有相應注釋( @JsonProperty
, @JsonIgnore
等)的java類重復嵌套json級別,則無需整體使用反序列化器。
如果要處理類中的未知字段,則可以使用@JsonAnySetter
進行此操作
我覺得你的問題可以通過設置來解決@JsonProperty("customfield_10700")
到外地deploymentEnvironments
,如下圖所示。 在這種情況下,您不需要自定義解串器。
public class IssueFieldsPoc implements Serializable {
@JsonProperty private String summary;
@JsonProperty private Date created;
@JsonProperty private List<String> labels;
@JsonProperty private Date resolutiondate;
@JsonProperty private Date updated;
@JsonProperty("customfield_10700")
private Set<String> deploymentEnvironments;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.