Dies gilt immer noch für Jackson Databind 2.7.0.
Die Jackson @JsonCreator
annotation 2.5 javadoc oder Jackson annotations documentation Grammatik (Konstruktor s und Factory-Methode s) lassen dass man Marke mehrere Konstrukteure glauben in der Tat.
Marker-Annotation, die zum Definieren von Konstruktoren und Factory-Methoden verwendet werden kann, die zum Instanziieren neuer Instanzen der zugeordneten Klasse verwendet werden.
auf den Code, wo die Schöpfer identifiziert werden, es sieht aus wie die Jackson CreatorCollector
ist ladenen Konstruktoren ignorieren, weil es nur checks the first argument of 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
ist der erste identifizierte Konstruktor Schöpfer.
newOne
ist der überladene Konstruktor Ersteller.
, dass dieser Code wie die bedeutet, dass
@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"); // raise error here
assertThat(new ObjectMapper().readValue("{\"value\":\"+336\"}", Phone.class).value).isEqualTo("+336");
Aber dieser Code funktioniert nicht:
@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");
Dies ist ein bisschen hacky und zukunftssicher nicht sein kann.
Die Dokumentation ist vage darüber, wie die Objekterstellung funktioniert; obwohl von dem, was ich aus dem Code zu sammeln, dann ist es, dass es möglich ist, verschiedene Methoden zu mischen:
Zum Beispiel kann man eine statische Factory-Methode kommentierte hat mit @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");
Es funktioniert, aber es ist nicht ideal. Am Ende könnte es sinnvoll sein, z.B. Wenn die JSON ist dynamische dann sollte man vielleicht einen Delegate-Konstruktor verwenden, um Nutzlast Variationen viel eleganter als mit mehreren kommentierten Konstruktoren zu behandeln.
Beachten Sie auch, dass Jackson orders creators by priority, zum Beispiel in diesem 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");
Dieses Mal Jackson wird einen Fehler nicht erhöhen, aber Jackson wird nur die Verwendung Delegierten Konstruktor Phone(Map<String, Object> properties)
, das heißt die Phone(@JsonProperty("value") String value)
ist nie benutzt.
Wie die Antwort darauf hinweist, nein, müssen Sie nur einen Konstruktor angeben. In Ihrem Fall, lassen Sie den, der mehrere Argumente braucht, das wird gut funktionieren. "Fehlende" Argumente werden NULL (für Objekte) oder Standardwerte (für Primitive) annehmen. – StaxMan
Danke. Mehrere Konstruktoren zuzulassen wäre jedoch eine nette Funktion. Eigentlich ist mein Beispiel ein bisschen erfunden. Das Objekt, das ich zu verwenden versuche, hat tatsächlich völlig verschiedene Argumentlisten, eine ist normal erstellt, die andere ist mit einem Throwable erstellt ... Ich werde sehen, was ich tun kann, vielleicht mit einem leeren Konstruktor und Getter/Setter für die Throwable – geejay
Ja, ich bin sicher, es wäre nett, aber Regeln können mit verschiedenen Permutationen ziemlich komplex werden. Es ist immer möglich, RFEs für neue Funktionen und Funktionen zu speichern. – StaxMan