Search code examples
javajsonjackson2

Jackson Deserialiser : use @JsonCreator AND @JsonProperty on field?


I'm trying to parse some Json into an Java object.
Some fields require custom behavior so i tried to use @JsonCreator on a constructor.

Well, it work, but for the other field annotate with @JsonProperty are not populated.
Didn't check yet, but i guess my object annotate with @JsonUnwrappedare not populated either.

In my search, i saw a comment that indicate that it is possible, but i can't figure how, if it is indeed possible.

There is around 400 field in the json, and only 5 or 6 that require custom behavior. So if i can avoid rewriting all constructor... that would be nice !

Exemple of what i tried :

public class MyObjectA {

  @JsonProperty("keyField1")
  private String myField1;

  @JsonUnwrapped
  private MyObjectB;

  private String[] myField2;

  @JsonCreator
  public MyObjectA(final Map<String, Object> properties){

    myField2  = ... //some Business logic 

  }

}

Junit :

ObjectMapper mapper = new ObjectMapper();
MyObjectA result = mapper.readValue(getJsonInputStream(JSON_FILE_PATH),MyObjectA.class);
Assert.notNull(result.getMyField1(),"should be populated")
Assert.notNull(result.getMyField2(),"should be populated")
Assert.notNull(result.getMyObjectB(),"should be populated")

Note : without the constructor, the other field are well populated


Solution

  • Here it is. See the difference between commented and non commented @JsonConstructor usage. I am handling property something as custom handling and leaving name to be called using setName. Hope that helps

    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import java.util.Map;
    
    public class Jackson2 {
    
    
        public static void main(String[] args) throws Exception {
    
            final ObjectMapper mapper = new ObjectMapper();
            final String jsonInString = "{\"name\":\"hello world\",\"something\":\"from string\"}";
            System.out.println(jsonInString);
    
            Foo newFoo = mapper.readValue(jsonInString, Foo.class);
            System.out.println(newFoo.getName());
            System.out.println(newFoo.getSomething());
        }
    }
    
    class Foo {
    
        @JsonProperty
        private String name;
        private String something;
    
        public String getSomething() {
            return something;
        }
    
        public void setSomething(String something) {
            this.something = something;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
    
        }
    
        Foo() {
        }
    
      // @JsonCreator
        public Foo(final Map<String, Object> properties) {
                System.out.println("printing.."+properties);
                something =  "Something from constructor";
         }
        @JsonCreator
        public Foo(@JsonProperty("something") String something ) {
                System.out.println("printing.."+name);
                this.something =  "Something from constructor appended"+something;
        }
    
    
    
    }
    

    So idea is that you use @JsonProperty in the constructor argument for properties you want to customize. :)