Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mix of standard and dynamic properties in Jackson mapping

Tags:

java

json

jackson

We are working with a REST service that provides json that will consist of some standard properties, as well as a number of dynamic properties.

For example:

{
  id: 123,
  name: "some name",
  custom_name: "Some value",
  some_other_custom_name: "Some other value",
}

Ideally, I'd like to have the class designed as follows:

public class MyObject{
  @JsonProperty int id;
  @JsonProperty String name;
  private Map<String, String> customVals;

  public int getId(){
    return id;
  }

  public String getName(){
    return name;
  }

  public String getCustomVal(String key){
    return customVals.get(key);
  }
}

Is there any way to convince Jackson to push the custom values into the Map (or achieve equivalent functionality)?

Right now, I'm just deserializing the whole object into a Map, and wrapping that in my business object, but it's not nearly as elegant as it would be if the deserialization would take care of it.

like image 960
Kevin Day Avatar asked Mar 15 '23 23:03

Kevin Day


1 Answers

You can use Jackson @JsonAnySetter and @JsonAnyGetter annotations.

Here is a complete example:

public class JacksonAnyGetter {

    static final String JSON = "{"
            + "  \"id\": 123,"
            + "  \"name\": \"some name\","
            + "  \"custom_name\": \"Some value\","
            + "  \"some_other_custom_name\": \"Some other value\""
            + "}";

    static class Bean {
        public int id;
        public String name;
        private Map<String, Object> properties = new HashMap<>();

        @JsonAnySetter
        public void add(String key, String value) {
            properties.put(key, value);
        }

        @JsonAnyGetter
        public Map<String, Object> getProperties() {
            return properties;
        }

        @Override
        public String toString() {
            return "Bean{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", properties=" + properties +
                    '}';
        }
    }

    public static void main(String[] args) throws IOException {
        final ObjectMapper mapper = new ObjectMapper();
        final Bean bean = mapper.readValue(JSON, Bean.class);
        System.out.println(bean);
        final String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(bean);
        System.out.println(json);
    }
}

Output:

Bean{id=123, name='some name', properties={custom_name=Some value, some_other_custom_name=Some other value}}

{
  "id" : 123,
  "name" : "some name",
  "custom_name" : "Some value",
  "some_other_custom_name" : "Some other value"
}
like image 148
Alexey Gavrilov Avatar answered Mar 24 '23 08:03

Alexey Gavrilov