I’m trying to deserialize a JSON file with the format of
JavaScript
x
{
"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
JavaScript
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:
JavaScript
public class LanguageWrapper {
@JsonDeserialize(using = Language.LanguageDeserializer.class)
public List<Language> languages = new ArrayList<>();
}
So when I try and use it
JavaScript
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?
Advertisement
Answer
Yeah was clearly overthinking it. As @chrylis suggested a Map
was the right direction to go in.
Simple as:
JavaScript
final TypeReference<HashMap<String, Language>> typeRef = new TypeReference<>() {};
final HashMap<String, Language> hashMap = objectMapper.readValue(new ClassPathResource("data/languages.json").getFile(), typeRef);