How to map unknown JSON properties with Jackson?

For a current project, I need to map a JSON object that have some known fields, and some "dynamics" fields. I don't want to ignore these fields, just to get them in a map inside my bean. After digging for 20 minutes, I finally found the right annotations to use: @JsonAnyGetter and @JsonAnySetter.

@JsonAnySetter is a simple marker that can be used to define a 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.

Here is a simple test:




import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.junit.Test;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.ObjectMapper;

public class DummyClass {

@Test
public void check() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();

// ---------------------------SER
// Classic
MyClass myClass1 = new MyClass();
myClass1.setProperty("John");

assertFalse(myClass1.hasUnknowProperties());
System.err.println(objectMapper.writeValueAsString(myClass1));

// With unknown properties
MyClass myClass2 = new MyClass();
myClass2.set("other-property", "a simple value");
myClass2.setProperty("John");

assertTrue(myClass2.hasUnknowProperties());
System.err.println(objectMapper.writeValueAsString(myClass2));

// ---------------------------DESER
MyClass mClass3 = objectMapper.readValue("{\"property\":\"John\"}",
MyClass.class);
assertFalse(mClass3.hasUnknowProperties());
assertEquals("John", mClass3.getProperty());

MyClass mClass4 = objectMapper
.readValue(
"{\"property\":\"John\",\"other-property\":\"a simple value\"}",
MyClass.class);
assertTrue(mClass4.hasUnknowProperties());
assertEquals("a simple value", mClass4.any().get("other-property"));
assertEquals("John", mClass4.getProperty());

}

public static class MyClass {

private String property;

private Map<String, String> other = new HashMap<String, String>();

public String getProperty() {
return property;
}

public void setProperty(String property) {
this.property = property;
}

@JsonAnyGetter
public Map<String, String> any() {
return other;
}

@JsonAnySetter
public void set(String name, String value) {
other.put(name, value);
}

public boolean hasUnknowProperties() {
return !other.isEmpty();
}

}
}

Labels: , ,