I'm trying to deserialize a JSON file with the format of
{
"English": {
"hex": "FF0000"
},
"Spanish": {
"hex": "0000FF"
},
"Japanese": {
"hex": "FFFF00"
}
}
But I don't want to create a class for each language (thousands) so I wrote a custom LanguageDeserializer
which gives me back the List<Language>
that I want
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;
}
I have a parent class to wrap the results:
public class LanguageWrapper {
@JsonDeserialize(using = Language.LanguageDeserializer.class)
public List<Language> languages = new ArrayList<>();
}
So when I try and use it
final LanguageWrapper languageWrapper = objectMapper.readValue(new ClassPathResource("data/languages.json").getFile(), LanguageWrapper.class);
The languages
list is always empty.
Can I do this without needing the LanguageDeserializer
or how do I make it work?
CodePudding user response:
Yeah was clearly overthinking it. As @chrylis suggested a Map
was the right direction to go in.
Simple as:
final TypeReference<HashMap<String, Language>> typeRef = new TypeReference<>() {};
final HashMap<String, Language> hashMap = objectMapper.readValue(new ClassPathResource("data/languages.json").getFile(), typeRef);
CodePudding user response:
If list (and plain Language
class) suits you better, you can do:
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());