Jackson bevorzugt privaten Konstruktor über @JsonCreator bei der Deserialisierung einer Klasse mit @JsonValue
Habe ich eine einfache Klasse mit einem privaten Konstruktor und eine statische Fabrik. Ich will die Klasse serialisieren, die als eine Reihe, also habe ich kommentierte den getter für das Feld mit @JsonValue
. Aber Jackson scheint zu bevorzugen, die privaten Konstruktor über die statische Fabrik, auch wenn ich kommentieren die statische Fabrik mit @JsonCreator
. Es funktioniert, wenn ich mit dem privaten Konstruktor mit @JsonIgnore
, aber das fühlt sich ein bisschen ab.
Ich habe gesehen, wie einige posts behaupten, dass @JsonCreator
funktioniert nur, wenn der Parameter sind kommentiert mit @JsonProperty
; das aber scheint der Fall für Objekte serialisiert als JSON-Objekte. Dieses Objekt wird serialisiert als Zahl, und somit gibt es keine Eigenschaft, um die Versorgung der annotation.
Gibt es etwas, was ich bin fehlt?
Beispiel Klasse:
package com.example;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import com.google.common.base.Preconditions;
public class NonNegative {
private final double n;
private NonNegative(double n) {
this.n = n;
}
@JsonCreator
public static NonNegative checked(double n) {
Preconditions.checkArgument(n >= 0.0);
return new NonNegative(n);
}
@JsonValue
public double getValue() {
return n;
}
@Override
public int hashCode() {
return Objects.hash(n);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof NonNegative) {
NonNegative that = (NonNegative) obj;
return Objects.equals(n, that.n);
}
return false;
}
}
Beispiel tests:
package com.example;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class NonNegativeTest {
private static final ObjectMapper MAPPER = new ObjectMapper();
@Test
public void itSerializesAndDeserializes() throws Exception {
NonNegative nonNegative = NonNegative.checked(0.5);
assertThat(MAPPER.readValue(MAPPER.writeValueAsString(nonNegative), NonNegative.class)).isEqualTo(nonNegative);
}
/* This test fails. */
@Test(expected = JsonMappingException.class)
public void itDoesNotDeserializeANegativeNumber() throws Exception {
MAPPER.readValue(MAPPER.writeValueAsString(-0.5), NonNegative.class);
}
}
- haben Sie versucht, annoting das argument der überprüften Methode mit @JsonProperty?
- Ich habe. Es hat nicht geholfen.
- Vielleicht relevant.
Du musst angemeldet sein, um einen Kommentar abzugeben.
In der Tat Jackson überschreiben JsonCreator-Methode-Konstruktor-Methode im Falle dass, wenn parameter Java-standard-Typ. Ich würde sagen, das ist ein bug in BasicDeserializerFactory#_handleSingleArgumentConstructor Methode.
So, das problem ist, dass die Konstruktor hat eine höhere Priorität als die statische factory-Methode im Falle dass, wenn, dass der Konstruktor und die statische factory-Methode hat die regelmäßige Java-Typ. Es gibt einige Möglichkeiten, um Abhilfe es.
Set creator Sichtbarkeit zu NON_PRIVATE:
Zweite Möglichkeit ist das löschen von statischen factory-Methode und Konstruktor verwenden. Ich zog Voraussetzungen.checkArgument an den Konstruktor (macht nicht viel... Nur wirft eine IllegalArgumentException, wenn die Bedingung nicht erfüllt ist):
Andere Möglichkeit ist die Verwendung von @JsonIgnore annotation, aber Sie erwähnen, dass Sie nicht wie dieser Ansatz 🙂
Update ich habe protokolliert einen Fehler: https://github.com/FasterXML/jackson-databind/issues/660
Update Jackson bug, der bevorzugt Konstruktor über statische factory-Methode gelöst wurde: https://github.com/FasterXML/jackson-databind/commit/257ae1c7a88c5ccec2882433a39c0df1de2b73aa
@JsonIgnore
obwohl...