Podczas próby otrzymania żądania JSON i przetworzenia go pojawia się następujący błąd:
org.codehaus.jackson.map.JsonMappingException: Nie znaleziono odpowiedniego konstruktora dla typu [typ prosty, klasa com.myweb.ApplesDO]: nie można utworzyć instancji z obiektu JSON (trzeba dodać / włączyć informacje o typie?)
Oto JSON, który próbuję wysłać:
{
"applesDO" : [
{
"apple" : "Green Apple"
},
{
"apple" : "Red Apple"
}
]
}
W kontrolerze mam następującą sygnaturę metody:
@RequestMapping("showApples.do")
public String getApples(@RequestBody final AllApplesDO applesRequest){
// Method Code
}
AllApplesDO to opakowanie ApplesDO:
public class AllApplesDO {
private List<ApplesDO> applesDO;
public List<ApplesDO> getApplesDO() {
return applesDO;
}
public void setApplesDO(List<ApplesDO> applesDO) {
this.applesDO = applesDO;
}
}
Jabłka DO:
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String appl) {
this.apple = apple;
}
public ApplesDO(CustomType custom){
//constructor Code
}
}
Myślę, że Jackson nie jest w stanie przekonwertować JSON na obiekty Java dla podklas. Proszę o pomoc w parametrach konfiguracyjnych dla Jacksona w celu konwersji JSON na obiekty Java. Korzystam z Spring Framework.
EDYCJA: Uwzględniono główny błąd, który powoduje ten problem w powyższej przykładowej klasie - Proszę spojrzeć na zaakceptowaną odpowiedź na rozwiązanie.
Odpowiedzi:
W końcu zrozumiałem na czym polega problem. To nie jest problem z konfiguracją Jacksona, jak wątpiłem.
W rzeczywistości problem dotyczył klasy ApplesDO :
Dla klasy zdefiniowano niestandardowego konstruktora, co czyni go domyślnym konstruktorem. Wprowadzenie fałszywego konstruktora spowodowało błąd, aby odejść:
źródło
Dzieje się tak z następujących powodów:
twoją klasę wewnętrzną należy zdefiniować jako statyczną
Możliwe, że nie masz domyślnego konstruktora w swojej klasie ( AKTUALIZACJA: Wydaje się, że tak nie jest)
Możliwe, że Twoi Settery nie są odpowiednio zdefiniowani lub nie są widoczni (np. Seter prywatny)
źródło
Chciałbym dodać do tego inne rozwiązanie, które nie wymaga fałszywego konstruktora. Ponieważ fałszywe konstruktory są nieco niechlujne, a następnie mylące. Możemy zapewnić bezpieczny konstruktor i dodając adnotacje do argumentów konstruktora, umożliwiamy Jacksonowi określenie odwzorowania między parametrem konstruktora a polem.
więc następujące będą również działać. Uwaga: ciąg znaków w adnotacji musi być zgodny z nazwą pola.
źródło
@JsonCreator
konstruktora za pomocą@JsonProperty
.Kiedy natknąłem się na ten problem, był to wynik próby użycia klasy wewnętrznej do pełnienia funkcji DO. Konstrukcja klasy wewnętrznej (po cichu) wymagała wystąpienia klasy obejmującej - która nie była dostępna dla Jacksona.
W takim przypadku przeniesienie klasy wewnętrznej do własnego pliku .java rozwiązało problem.
źródło
Zasadniczo ten błąd występuje, ponieważ nie tworzymy domyślnego konstruktora, ale w moim przypadku problem pojawił się tylko dlatego, że utworzyłem używaną klasę obiektów w klasie nadrzędnej. To zmarnowało mój cały dzień.
źródło
static
.Reguła kciuka : dodaj domyślny konstruktor dla każdej klasy użytej jako klasa odwzorowania. Przegapiłeś to i problem się pojawia!
Wystarczy dodać domyślny konstruktor i powinien on działać.
źródło
Czy możesz przetestować tę strukturę? Jeśli dobrze pamiętam, możesz użyć tego w ten sposób:
Po drugie, dodaj domyślny konstruktor do każdej klasy, która również może pomóc.
źródło
Musisz stworzyć atrapę pustego konstruktora w naszej klasie modeli, więc podczas mapowania jsona ustawia się go metodą setter.
źródło
Jeśli zaczniesz dodawać adnotacje do konstruktora, musisz dodać adnotacje do wszystkich pól.
Uwaga: moje pole Staff.name jest odwzorowane na „ANOTHER_NAME” w ciągu JSON.
źródło
Musisz zdać sobie sprawę z dostępnych opcji Jacksona na deserializację. W Javie nazwy argumentów metod nie występują w skompilowanym kodzie. Dlatego Jackson zazwyczaj nie może używać konstruktorów do tworzenia dobrze zdefiniowanego obiektu ze wszystkim, co już zostało ustawione.
Tak więc, jeśli istnieje pusty konstruktor i istnieją również setery, używa pustego konstruktora i seterów. Jeśli nie ma seterów, używa się do tego trochę mrocznej magii (odbicia).
Jeśli chcesz użyć konstruktora z Jacksonem, musisz użyć adnotacji wspomnianych przez @PiersyP w jego odpowiedzi. Możesz także użyć wzorca konstruktora. Jeśli napotkasz wyjątki, powodzenia. Obsługa błędów w Jacksonie jest do bani, trudno zrozumieć, że bełkot w komunikatach o błędach.
źródło
Jeśli chodzi o ostatnią publikację, miałem ten sam problem, gdy wygenerowanie problemu spowodowało użycie Lombok 1.18. *.
Moim rozwiązaniem było dodanie @NoArgsConstructor (konstruktor bez parametrów), ponieważ @Data domyślnie zawiera @RequiredArgsConstructor (konstruktor z parametrami).
Dokumentacja lombok https://projectlombok.org/features/all
To rozwiązałoby problem:
źródło
Problemem może być także awaria niestandardowych serializatorów / dezrializatorów firmy jackson. Chociaż to nie twoja sprawa, warto o tym wspomnieć.
Napotkałem ten sam wyjątek i tak właśnie było.
źródło
Dla mnie to działało, ale aktualizacja bibliotek spowodowała pojawienie się tego problemu. Problemem było zorganizowanie takiej klasy:
Za pomocą lombok:
Wracając do
Naprawiono problem. Nie jestem pewien, dlaczego, ale chciałem to udokumentować na przyszłość.
źródło