簡體   English   中英

Jackson ObjectMapper 在轉換為 POJO 時忽略某些鍵

[英]Jackson ObjectMapper ignore certain keys when converting to POJO

這是我的 class

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.*;

public class Util {

    public static void main(String[] args) throws JsonProcessingException {
        String json = "{ \"argA\" : 5, \"unneededkey\" : 6}";
        ObjectMapper mapper = new ObjectMapper();
        MyObject object3 = mapper.readValue(json, MyObject.class);
        System.out.println(object3);

    }
    @ToString
    @RequiredArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class MyObject {
        public MyObject(int argA) {
            this.argA = argA;
        }

        public MyObject(int argA, boolean argB) {
            this.argA = argA;
            this.argB = argB;
        }

        public MyObject(int argA, int argC, int argD) {
            this.argA = argA;
            this.argC = argC;
            this.argD = argD;
        }

        public MyObject(int argA, String argE) {
            this.argA = argA;
            this.argE = argE;
        }

        public int argA = 1;
        public boolean argB;
        public int argC = 4;
        public int argD = 5;
        public String argE;
    }
}

@JsonIgnoreProperties(ignoreUnknown = true) 有效,但這會忽略所有不需要的鍵。 如果我只想忽略某些不需要的鍵,並且如果我得到的鍵不屬於我的 object 構造函數或在不需要的集合中,它會拋出異常。

我建議的方法:

在 class 上保留@JsonIgnoreProperties(ignoreUnknown = true)注釋。

假設以下輸入 JSON:

{
    "argA": 5,
    "unneededkey": 6,
    "unexpectedKey": 99
}

創建一個包含允許字段名稱的集合(其中“允許”是MyObject class 中存在的字段,或者可以安全地忽略它):

Set<String> allowedFields = new HashSet(Arrays.asList(
            "argA", "argB", "argC", "argD", "argE",
            "unneededkey", "unneededkey2"));

然后對 JSON 進行如下處理:

ObjectMapper mapper = new ObjectMapper();

JsonNode rootNode = mapper.readTree(json);
Iterator<String> fieldNames = rootNode.fieldNames();
boolean fieldFailure = false;
Set<String> unexpectedFields = new HashSet();

while (fieldNames.hasNext()) {
    String fieldName = fieldNames.next();
    if (!allowedFields.contains(fieldName)) {
        fieldFailure = true;
        unexpectedFields.add(fieldName);
    }
}

然后,您可以根據 boolean fieldFailure選擇如何繼續。 要么拋出異常(使用意外字段名稱列表獲取信息),要么以通常的方式創建 object:

MyObject object = mapper.readValue(json, MyObject.class);

不利的一面是它可能會遍歷 JSON 兩次 - 一次檢查問題,再次(假設沒有問題)反序列化數據。

注意事項:

(1) 上面的代碼假設一個扁平的 JSON 結構 - 沒有嵌入對象 - 這與您在問題中的內容相匹配。 為了更靈活,您可以使用以下findKeys方法遞歸訪問所有節點:

Map<String, Object> treeMap = mapper.readValue(json, Map.class);
List<String> keys  = Lists.newArrayList();
List<String> result = findKeys(treeMap, keys);

private List<String> findKeys(Map<String, Object> treeMap, List<String> keys) {
    treeMap.forEach((key, value) -> {
        if (value instanceof LinkedHashMap) {
            Map<String, Object> map = (LinkedHashMap) value;
            findKeys(map, keys);
        }
        keys.add(key);
    });

    return keys;
}

致謝:有關詳細信息,請參閱此答案

(2) 我考慮了一個自定義反序列化器:

public class MyDeserializer extends StdDeserializer<Util.MyObject> { 
    ...
}

但是您仍然會遇到同樣的問題 - 更不用說調用正確的構造函數所需的額外工作,具體取決於它找到的非空字段值的特定組合。

暫無
暫無

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

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