簡體   English   中英

用Jackson和@JsonCreator反序列化JSON

[英]Deserialize JSON with Jackson and @JsonCreator

我從正在開發的第三方工具接收JSON文檔,即JSON經常擴展。 我想堅持使用最簡單的反序列化機制,以避免自定義反序列化器附帶的增加的維護。

這是JSON的相關部分:

{
"key1": "value1",
"key2": "value2",
"variants": {
    "columns": ["chr", "pos", "id", "ref", "alt", "qual", "filter", "type", "genotype", "alignpos", "basepos", "signalpos"],
    "rows": [
        ["17", 19561093, ".", "G", "C", 51, "PASS", "SNV", "het.", 97, 147, 1761],
        ["17", 19561123, ".", "T", "G", 51, "PASS", "SNV", "het.", 127, 177, 2120],
        ["17", 19561149, ".", "G", "A", 51, "PASS", "SNV", "het.", 153, 203, 2432]],
    "xranges": [
        [829, 1129],
        [1480, 1780],
        [1492, 1792]],
}}

問題出在variants標記上,尤其是“行”。 看起來好像用@JsonValue批注對“行”進行了序列化,以消除否則將成為每個“行”一部分的字段名。 而是將一個附加的“列”字段序列化為至少提及一次列名。

沒有variants標簽,我已經成功地使用ObjectMapper將JSON反序列化為POJO:

public class Pojo {
    private String key1;
    private String key2;
    public String getKey1() {
        return key1;
    }
    public void setKey1(String key1) {
        this.key1 = key1;
    }
    public String getKey2() {
        return key2;
    }
    public void setKey2(String key2) {
        this.key2 = key2;
    }
}

public static void main(String[] args) {
    final ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    Pojo pojo = objectMapper.readValue(jsonFile, Pojo.class);
}

現在,為了反序列化變體,我將其添加到原始POJO中

@JsonProperty("variants")
private PojoVariants pojoVariants;

然后,實現PojoVariants

public class PojoVariants {

    @JsonProperty("columns")
    private String[] columnNames;

    @JsonProperty("rows")
    private PojoVariant[] pojoVariantArr;

    public String[] getColumnNames() {
        return columnNames;
    }

    public void setColumnNames(String[] columnNames) {
        this.columnNames = columnNames;
    }

    public PojoVariant[] getPojoVariantArr() {
        return pojoVariantArr;
    }

    public void setPojoVariantArr(PojoVariant[] pojoVariantArr) {
        this.pojoVariantArr = pojoVariantArr;
    }

}

最后是PojoVariant

@JsonPropertyOrder({
        "chr", "pos",
        "id", "ref", "alt",
        "quality", "filter", "type", "genotype",
        "alignPos", "basePos", "signalPos" })
public class PojoVariant {

    private String chr;
    private int pos;

    private String id;
    private String ref;
    private String alt;

    private int quality;
    private String filter;
    private String type;
    private String genotype;

    private int alignPos;
    private int basePos;
    private int signalPos;

    @JsonCreator
    public PojoVariant(
            String chr, int pos,
            String id, String ref, String alt,
            int quality, String filter, String type, String genotype,
            int alignPos, int basePos, int signalPos) {

    }

}

設置@JsonPropertyOrder,我希望傑克遜能夠弄清楚我想將每個“行”讀入PojoVariant實例。 但是,使用原始的main方法,我得到此堆棧跟蹤:

org.codehaus.jackson.map.JsonMappingException: Argument #0 of constructor [constructor for my.json.stuff.PojoVariant, annotations: {interface org.codehaus.jackson.annotate.JsonCreator=@org.codehaus.jackson.annotate.JsonCreator()}] has no property name annotation; must have name when multiple-paramater constructor annotated as Creator

我知道傑克遜希望我用屬性名稱注釋構造函數參數。 但是JSON不包含任何開頭。 我想念什么? 還是根本不支持這種方法-我必須實現自定義解串器嗎?

jackson注釋javadoc中@JsonPropertyOrder用於序列化,而不是反序列化:

可用於定義序列化對象屬性時使用的排序(可能是部分)的注釋。

另外,在使用@JsonCreator注釋構造函數時,構造函數必須為:

  • 對於參數,不帶JsonProperty批注的單參數構造函數 / factory方法:如果是這樣,這就是所謂的“委托創建者”,在這種情況下, Jackson首先將JSON綁定到參數的類型中,然后調用creator
  • 構造函數/工廠方法,其中每個參數都用JsonProperty或JacksonInject注釋,以指示要綁定的屬性的名稱。

問題是您嘗試從json列表["17", 19561093, ".", ..]反序列PojoVariant 傑克遜很聰明,但沒有那么聰明。 在這里他需要一些幫助,您可以幫助他實現自定義解串器。 我們不想這樣做,所以我們希望可以找到其他東西。

提示來自@JsonCreator javadoc(第一個項目符號,粗體文本)。 並且,由於Jackson知道如何將列表綁定到對象數組中,因此我們可以像下面這樣重寫PojoVariant構造函數:

@JsonCreator
public PojoVariant(Object[] params) {
    this.chr = (String) params[0];
    this.pos = (int) params[1];
    this.id = (String) params[2];
    this.ref = (String) params[3];
    this.alt = (String) params[4];
    this.quality = (int) params[5];
    this.filter = (String) params[6];
    this.type = (String) params[7];
    this.genotype = (String) params[8];
    this.alignPos = (int) params[9]; 
    this.basePos = (int) params[10];
    this.signalPos = (int) params[11];
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM