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());
我正在尝试反序列化 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());