Jackson 反序列化 JSON 有很多动态节点

Jackson deserialise JSON with many dynamic nodes

我正在尝试反序列化 JSON 格式为

的文件
{
  "English": {
    "hex": "FF0000"
  },
  "Spanish": {
    "hex": "0000FF"
  },
  "Japanese": {
    "hex": "FFFF00"
  }
}

但我不想为每种语言(数千种)创建一个 class,所以我写了一个自定义 LanguageDeserializer,它返回我想要的 List<Language>

static class LanguageDeserializer extends StdDeserializer<ArrayList<Language>> {

//...

@Override
public ArrayList<Language> deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException {
    final JsonNode node = jp.getCodec().readTree(jp);
    final Iterator<Map.Entry<String, JsonNode>> nodes = node.fields();

    final ArrayList<Language> results = new ArrayList<>();

    while (nodes.hasNext()) {
        // Builds up the object from the nodes

        results.add(builder.build());
    }

    return results;
}

我有一个父 class 来包装结果:

public class LanguageWrapper {

    @JsonDeserialize(using = Language.LanguageDeserializer.class)
    public List<Language> languages = new ArrayList<>();

}

所以当我尝试使用它时

final LanguageWrapper languageWrapper = objectMapper.readValue(new ClassPathResource("data/languages.json").getFile(), LanguageWrapper.class);

languages 列表总是空的。

我可以在不需要 LanguageDeserializer 的情况下执行此操作吗?或者我该如何让它工作?

是的,显然是想多了。正如@chrylis 所建议的那样,Map 是正确的进入方向。

简单如:

final TypeReference<HashMap<String, Language>> typeRef = new TypeReference<>() {};
final HashMap<String, Language> hashMap = objectMapper.readValue(new ClassPathResource("data/languages.json").getFile(), typeRef);

如果列表(和普通 Language class)更适合你,你可以这样做:

TypeReference<Map<String, Map<String, String>>> typeReference = new TypeReference<>() {};
List<Language> languages = new ObjectMapper().readValue(new ClassPathResource("data/languages.json").getFile(), typeReference)
                .entrySet()
                .stream()
                .map(entry -> new Language(entry.getKey(), entry.getValue().get("hex")))
                .collect(Collectors.toList());