Eine andere Option ist die Verwendung von InjectableValues und @JacksonInject . Es ist sehr nützlich, wenn Sie nicht immer den gleichen Wert verwenden müssen, sondern einen von DB oder einem anderen Ort für den speziellen Fall erhalten. Hier ist ein Beispiel für die Verwendung von JacksonInject
:
protected static class Some {
private final String field1;
private final String field2;
public Some(@JsonProperty("field1") final String field1,
@JsonProperty("field2") @JacksonInject(value = "defaultValueForField2",
useInput = OptBoolean.TRUE) final String field2) {
this.field1 = requireNonNull(field1);
this.field2 = requireNonNull(field2);
}
public String getField1() {
return field1;
}
public String getField2() {
return field2;
}
}
@Test
public void testReadValueInjectables() throws JsonParseException, JsonMappingException, IOException {
final ObjectMapper mapper = new ObjectMapper();
final InjectableValues injectableValues =
new InjectableValues.Std().addValue("defaultValueForField2", "somedefaultValue");
mapper.setInjectableValues(injectableValues);
final Some actualValueMissing = mapper.readValue("{\"field1\": \"field1value\"}", Some.class);
assertEquals(actualValueMissing.getField1(), "field1value");
assertEquals(actualValueMissing.getField2(), "somedefaultValue");
final Some actualValuePresent =
mapper.readValue("{\"field1\": \"field1value\", \"field2\": \"field2value\"}", Some.class);
assertEquals(actualValuePresent.getField1(), "field1value");
assertEquals(actualValuePresent.getField2(), "field2value");
}
Denken Sie daran, dass wenn Sie den Konstruktor zum Erstellen der Entität verwenden (dies geschieht normalerweise, wenn Sie @Value oder @AllArgsConstructor in lombok verwenden ) und Sie @JacksonInject
nicht den Konstruktor, sondern die Eigenschaft verwenden, funktioniert dies nicht wie erwartet - Wert des injizierten Feld wird immer Wert in json außer Kraft setzen, egal ob Sie setzen useInput = OptBoolean.TRUE
in @JacksonInject
. Dies liegt daran, dass Jackson diese Eigenschaften nach dem Aufruf des Konstruktors einfügt (auch wenn die Eigenschaft lautet final
). Das Feld wird im Konstruktor auf den richtigen Wert gesetzt, aber dann überschrieben (siehe: https://github.com/FasterXML/jackson-databind/). Issues / 2678 und https://github.com/rzwitserloot/lombok/issues/1528#issuecomment-607725333für weitere Informationen), wird dieser Test leider vorbei :
protected static class Some {
private final String field1;
@JacksonInject(value = "defaultValueForField2", useInput = OptBoolean.TRUE)
private final String field2;
public Some(@JsonProperty("field1") final String field1,
@JsonProperty("field2") @JacksonInject(value = "defaultValueForField2",
useInput = OptBoolean.TRUE) final String field2) {
this.field1 = requireNonNull(field1);
this.field2 = requireNonNull(field2);
}
public String getField1() {
return field1;
}
public String getField2() {
return field2;
}
}
@Test
public void testReadValueInjectablesIncorrectBehavior() throws JsonParseException, JsonMappingException, IOException {
final ObjectMapper mapper = new ObjectMapper();
final InjectableValues injectableValues =
new InjectableValues.Std().addValue("defaultValueForField2", "somedefaultValue");
mapper.setInjectableValues(injectableValues);
final Some actualValueMissing = mapper.readValue("{\"field1\": \"field1value\"}", Some.class);
assertEquals(actualValueMissing.getField1(), "field1value");
assertEquals(actualValueMissing.getField2(), "somedefaultValue");
final Some actualValuePresent =
mapper.readValue("{\"field1\": \"field1value\", \"field2\": \"field2value\"}", Some.class);
assertEquals(actualValuePresent.getField1(), "field1value");
assertEquals(actualValuePresent.getField2(), "somedefaultValue");
}
Hoffe das hilft jemandem mit einem ähnlichen Problem.
PS Ich benutze Jackson v. 2.9.6