This is still saved for the Jackson 2.7.0 data file.
The Jackson @JsonCreator annotation 2.5 javadoc or Jackson annotation documentation (constructor s and factory method s ) suggest that several constructors can be noted.
Token annotations that can be used to define factory constructors and methods as one to use for instances of new instances of the associated class.
Looking at the code that identifies the creators, it seems that Jackson CreatorCollector ignores overloaded constructors because it only checks the first argument to the constructor .
Class<?> oldType = oldOne.getRawParameterType(0); Class<?> newType = newOne.getRawParameterType(0); if (oldType == newType) { throw new IllegalArgumentException("Conflicting "+TYPE_DESCS[typeIndex] +" creators: already had explicitly marked "+oldOne+", encountered "+newOne); }
oldOne is the first identified creator of the constructor.newOne is the creator of the overloaded constructor.
This means that such code will not work.
@JsonCreator public Phone(@JsonProperty("value") String value) { this.value = value; this.country = ""; } @JsonCreator public Phone(@JsonProperty("country") String country, @JsonProperty("value") String value) { this.value = value; this.country = country; } assertThat(new ObjectMapper().readValue("{\"value\":\"+336\"}", Phone.class).value).isEqualTo("+336");
But this code will work:
@JsonCreator public Phone(@JsonProperty("value") String value) { this.value = value; enabled = true; } @JsonCreator public Phone(@JsonProperty("enabled") Boolean enabled, @JsonProperty("value") String value) { this.value = value; this.enabled = enabled; } assertThat(new ObjectMapper().readValue("{\"value\":\"+336\"}", Phone.class).value).isEqualTo("+336"); assertThat(new ObjectMapper().readValue("{\"value\":\"+336\",\"enabled\":true}", Phone.class).value).isEqualTo("+336");
This is a bit hacky and cannot be future proof .
The documentation is unclear as to how object creation works; from what I am compiling from the code, however, is that you can mix different methods:
For example, you can use the static factory method annotated with @JsonCreator
@JsonCreator public Phone(@JsonProperty("value") String value) { this.value = value; enabled = true; } @JsonCreator public Phone(@JsonProperty("enabled") Boolean enabled, @JsonProperty("value") String value) { this.value = value; this.enabled = enabled; } @JsonCreator public static Phone toPhone(String value) { return new Phone(value); } assertThat(new ObjectMapper().readValue("\"+336\"", Phone.class).value).isEqualTo("+336"); assertThat(new ObjectMapper().readValue("{\"value\":\"+336\"}", Phone.class).value).isEqualTo("+336"); assertThat(new ObjectMapper().readValue("{\"value\":\"+336\",\"enabled\":true}", Phone.class).value).isEqualTo("+336");
It works, but it is not perfect. In the end, it might make sense, for example. if json is dynamic, then it might be worth using the delegate constructor to handle payload changes much more elegantly than with a few annotated constructors.
Also note that Jackson orders creators by priority , for example, in this code:
// Simple @JsonCreator public Phone(@JsonProperty("value") String value) { this.value = value; } // more @JsonCreator public Phone(Map<String, Object> properties) { value = (String) properties.get("value"); // more logic } assertThat(new ObjectMapper().readValue("\"+336\"", Phone.class).value).isEqualTo("+336"); assertThat(new ObjectMapper().readValue("{\"value\":\"+336\"}", Phone.class).value).isEqualTo("+336"); assertThat(new ObjectMapper().readValue("{\"value\":\"+336\",\"enabled\":true}", Phone.class).value).isEqualTo("+336");
This time Jackson will not throw an error, but Jackson will only use the Phone(Map<String, Object> properties) delegate constructor Phone(Map<String, Object> properties) , which means that Phone(@JsonProperty("value") String value) never used.