Skip to content
Advertisement

Jackson deserialise JSON with many dynamic nodes

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?

Advertisement

Answer

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);
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement