如何告诉 Jackson 使子元素成为顶级元素

How to tell Jackson to make a sub-element the top level element

我知道如何在 Jackson 中 unwrap 一个 Object 但我找不到任何关于如何 unwrap 两个的例子图层。

Sharepoint API EndPoints return 以下格式的所有内容:

{
    "d": {
        "results": [
            {
               /* lots objects with lots of properties 
                  that are irrelevant to the question */
            }
        ]
    }
}

我尝试了以下方法,它没有使 results 值成为顶级对象。

this.om.readerFor(new TypeReference<List<User>>() {})
       .withRootName("d")
       .readValue(response.parseAsString());

如何告诉 Jackson 开始将 results 解析为顶级 Array 而无需创建自定义对象层次结构 而无需编写自定义解串器 。我有一个自定义对象,它被注释为将填充,我想要 TypeSafety 所以 Map<String,Object> 不是我想要的。

@JsonRootName("d")
class Data {
    public Map<String, Object>[] results;
}

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);

Map<String, Object> results = new LinkedHashMap<>();
results.put("key1", "val1");
results.put("key2", "val2");

Data expected = new Data();
expected.results = new Map[1];
expected.results[0] = results;

String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(expected);
Data actual = mapper.readerFor(Data.class).readValue(json);

Json 字符串看起来像:

{
  "d" : {
    "results" : [ {
      "key1" : "val1",
      "key2" : "val2"
    } ]
  }
}

P.S. 如果您不关心创建对象并且 Map<String, Object> 适合您,那么您可以像这样使用。

Map<String, Object> results = (Map<String, Object>)((List<?>)mapper.readerFor(Map.class).<Map<String, Map<String, ?>>>readValues(json).next().get("d").get("results")).get(0);

可能不是最有效的方法,但可以尝试先将对象解析为树,然后导航到您需要的节点。像这样:

mapper.readerFor(new TypeReference<List<User>>() {}).readValue(mapper.readTree(json).get("d").get("results"))‌​;

更易于阅读:

mapper.convertValue(mapper.readTree(json).get("d").get("‌​results"), new TypeReference<List<User>>() {});