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: deserialization, jackson, serialization