DÜZENLEME : Bakın, Jackson'ın geliştiricilerinin bir blog gönderisinde , 2.12'nin yapıcı enjeksiyonu ile ilgili gelişmeler görebileceği görülüyor. (Bu düzenlemenin yapıldığı tarihteki mevcut sürüm 2.11.1'dir)
Belirsiz 1 bağımsız değişkenli oluşturucularla sorunları çözme / hafifletme dahil olmak üzere Oluşturucu oluşturucuların otomatik algılamasını iyileştirin (yetki verme ve özellikler)
Bu, Jackson databind 2.7.0 için hala geçerlidir.
Jackson @JsonCreator
açıklama 2.5 javadoc veya Jackson'un açıklamalar belgelere dilbilgisi ( kurucu lar ve fabrika yöntemi ler ) Bir yapabilmesi gerçekten inanalım işaretlemek birden fazla kurucuya.
Oluşturucuları ve fabrika yöntemlerini, ilişkili sınıfın yeni örneklerini somutlaştırmak için kullanılacak biri olarak tanımlamak için kullanılabilen işaretleyici ek açıklaması.
Yaratıcıların belirlendiği koda bakıldığında , Jackson aşırı yüklenmiş kurucularıCreatorCollector
görmezden geliyor gibi görünüyor çünkü sadece kurucunun ilk argümanını kontrol ediyor .
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
tanımlanmış ilk kurucu yaratıcısıdır.
newOne
aşırı yüklenmiş yapıcı yaratıcısıdır.
Bu, böyle bir kodun çalışmayacağı anlamına gelir
@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");
assertThat(new ObjectMapper().readValue("{\"value\":\"+336\"}", Phone.class).value).isEqualTo("+336");
Ancak bu kod çalışacaktır:
@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");
Bu biraz karmaşıktır ve ileride kanıtı olmayabilir .
Dokümantasyon, nesne oluşturmanın nasıl çalıştığı konusunda belirsizdir; koddan topladığım kadarıyla, farklı yöntemleri karıştırmak mümkün:
Örneğin, bir statik fabrika yöntemi ile açıklanmış olabilir @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");
Çalışıyor ama ideal değil. JSON yani eğer Sonunda, örneğin anlamlı olamaz dinamik sonra belki bir çoklu açıklamalı kurucular ile çok daha zarif kulp yük değişimlerine bir temsilci kurucusunu kullanmak bakmak gerekir.
Ayrıca, Jackson'ın içerik oluşturucuları öncelik sırasına göre sıraladığını unutmayın , örneğin bu kodda:
@JsonCreator
public Phone(@JsonProperty("value") String value) {
this.value = value;
}
@JsonCreator
public Phone(Map<String, Object> properties) {
value = (String) properties.get("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");
Bu sefer Jackson bir hata ortaya çıkarmayacak, ancak Jackson yalnızca delege kurucusunu kullanacak Phone(Map<String, Object> properties)
, yani Phone(@JsonProperty("value") String value)
hiçbir zaman kullanılmayacak.