Search code examples
javajsonjacksonjson-deserializationjsonserializer

Skipping nested field with Jackson data binding?


How must I bind (bidirectional) the following json snippet to the Java objects below with Jackson?

I want the key/value pairs of the Json newsletter node to end up in the Map of the newsletter field. What must be the Jackson config (annotations and others) to bind this ? Sorry, I don't know how :( (using the latest version of Jackson).

The Json format below is fixed, I receive it from a third party rest service (I can't change it). I can change the java code, but prefer the setup below.

JSON:

{
    "newsletter": {
        "key1": "value1",
        "key2": "value2",
        "key3": "value3"
    }
}

The Java Objects:

class Preferences {
    private NewsLetter newsLetter;
    // getter/setter for field newsLetter.
}

class NewsLettter {
    private Map<String, String> properties;
    // getter/setter for field properties.
}

Solution

  • You could simply use @JsonAnySetter for deserialization

    Marker annotation that can be used to define a non-static, two-argument method (first argument name of property, second value to set), to be used as a "fallback" handler for all otherwise unrecognized properties found from JSON content.

    And @JsonAnyGetter for serialization.

    Marker annotation that can be used to define a non-static, no-argument method or member field as something of a reverse of JsonAnySetter method; basically being used like a getter but such that contents of the returned Map (type must be Map) are serialized as if they were actual properties of the bean that contains method/field with this annotations

    public class Newsletter {
    
        private final Map<String, String> properties = new HashMap<>();
    
        @JsonAnySetter
        public void addProperty(String name, String value) {
            properties.put(name, value);
        }
    
        @JsonAnyGetter
        public Map<String, String> getProperties() {
            return properties;
        }
    }
    

    This should work just fine for your use case.

    Test

    public class Main {
    
        public static void main(String[] args) throws Exception {
            String json
                    = "{\n"
                    + "    \"newsletter\": {\n"
                    + "        \"key1\": \"value1\",\n"
                    + "        \"key2\": \"value2\",\n"
                    + "        \"key3\": \"value3\"\n"
                    + "    }\n"
                    + "}";
    
            ObjectMapper mapper = new ObjectMapper();
            Preferences prefs = mapper.readValue(json, Preferences.class);
            Map<String, String> properties = prefs.getNewsletter().getProperties();
            for (Map.Entry<String, String> prop: properties.entrySet()) {
                System.out.println(prop.getKey() + ":" + prop.getValue());
            }
        }
    }
    

    See Also: