Serializacja z Jacksonem (JSON) - uzyskiwanie „Nie znaleziono serializatora”?

262

Mam wyjątek, gdy próbuję serializować bardzo prosty obiekt za pomocą Jacksona. Błąd:

org.codehaus.jackson.map.JsonMappingException: Nie znaleziono serializatora dla klasy MyPackage.TestA i nie znaleziono właściwości do utworzenia BeanSerializer (aby uniknąć wyjątku, wyłącz SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS))

Poniżej znajduje się prosta klasa i kod do serializacji.

Czy ktoś może mi powiedzieć, dlaczego dostaję ten błąd?

public class TestA {
    String SomeString = "asd";
}

TestA testA = new TestA();
ObjectMapper om = new ObjectMapper();
try {
    String testAString = om.writeValueAsString(testA); // error here!

    TestA newTestA = om.readValue(testAString, TestA.class);
} catch (JsonGenerationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (JsonMappingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
Przetrząsać
źródło
Napisałem post na temat pisania niestandardowego serializatora z Jacksonem, który może być dla niektórych pomocny.
Sam Berry

Odpowiedzi:

329

Jak już opisano, domyślną konfiguracją ObjectMapperinstancji jest dostęp tylko do właściwości, które są polami publicznymi lub mają publiczne obiekty pobierające / ustawiające. Alternatywą dla zmiany definicji klasy w celu upublicznienia pola lub zapewnienia publicznego gettera / settera jest określenie (do podstawy VisibilityChecker) innej reguły widoczności właściwości. Jackson 1.9 zapewnia ObjectMapper.setVisibility()wygodę. Na przykład w pierwotnym pytaniu prawdopodobnie skonfigurowałbym to jako

myObjectMapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);

Dla Jacksona> 2.0:

myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

Aby uzyskać więcej informacji i szczegółów na temat powiązanych opcji konfiguracji, polecam przejrzenie JavaDocs naObjectMapper.setVisibility() .

Programista Bruce
źródło
59
To zadziałało dla mnie. Począwszy od Jackson 2.0, ObjectMapper # setVisibility przyjmuje jako argument pierwszy argument PropertyAccessor. Odpowiednik oneliner to myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
Dan Robinson
@ DanRobinson użyłem tego samego. Ale tak naprawdę generuję plik yaml. więc dla JSONString as: {"term":{"call_failed":"true"}}generuje strukturę yaml jako: filter: map: term: map: call_failed: "true"Dlaczego generuje mapsłowo kluczowe? Jak mogę to usunąć?
Manish Kumar
7
Prawdopodobnie spędziłem 8 godzin z tym błędem, nie zdając sobie sprawy, że moja metoda gettera nie miała na nim „publicznego”. Więc głupie
Mike Kellogg
1
Otrzymuję ten błąd podczas konwertowania ClientResponse na ciąg znaków za pomocą mapowania obiektów
VdeX
1
Możesz także dodać adnotację @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)nad swoją klasą
veben,
74

Aby Jackson mógł serializować tę klasę, SomeStringpole musi być albo public(teraz jest to izolacja na poziomie pakietu), albo musisz zdefiniować dla niego metody pobierające i ustawiające.

Chris
źródło
5
Uwaga: ta odpowiedź jest niepoprawna - pole nie musi być publiczne ani mieć metody pobierającej i ustawiającej. W innej odpowiedzi na to pytanie podałem alternatywną konfigurację, która nie wymaga (pierwotnej) serializacji zmian w oryginalnej strukturze danych.
Programista Bruce
9
Odpowiedź jest przydatna, nawet jeśli nie w 100% precyzyjna. Zapomniałem o „upublicznieniu” moich warów, a to zwróciło na to uwagę. Dzięki!
ChrisPhoenix 17.04.15
53

Mam ten sam problem w kodzie źródłowym. Właśnie dodałem

rębacz

i

seter

problem rozwiązany.

Günay Gültekin
źródło
1
Próbowałem wielu różnych rzeczy, a rozwiązanie jest tak proste, jak to ... i mówi dość wyraźnie: „nie znaleziono właściwości do utworzenia”.
aks
2
@PhilipRego Ma na myśli, że dodał gettera i setera dla boiska.
Paul
Używam biblioteki lombok, więc po prostu dodaję notację Getter and Setter. I wszystko było w porządku. Dzięki.
Rahmat Hidayat
tak, gettery i setery są używane do serializacji Jacksona. / Deserializacja
Ikhiloya Imokhai
25

Problem w moim przypadku polegał na tym, że Jackson próbował serializować pusty obiekt bez atrybutów ani metod.

Jak zasugerowano w wyjątku, dodałem następujący wiersz, aby uniknąć awarii pustych ziaren:

Dla Jackson 1.9

myObjectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);

Dla Jackson 2.X

myObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

Prosty przykład można znaleźć na temat Jacksona wyłączyć fail_on_empty_beans

Martín C.
źródło
9

Miałem ten sam problem z klasą potomną, w której miałem kontrolę, mapowanie obiektów było we wspólnym module i było niedostępne. Rozwiązałem go, dodając adnotację do mojej klasy podrzędnej, której obiekt miał być serializowany.

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
Pavan Kumar
źródło
7

Jeśli możesz edytować klasę zawierającą ten obiekt, zwykle po prostu dodam adnotację

import com.fasterxml.jackson.annotation.JsonIgnore;

@JsonIgnore 
NonSerializeableClass obj;
ZiglioUK
źródło
2
Ten błąd jest uruchamiany również wtedy, gdy klasa ma metodę o nazwie zaczynającej się od get ... Na przykład NonSerializableClass getMyNonSerializableObject (). Jackson próbuje serializować to i kończy się niepowodzeniem. Aby rozwiązać ten problem, po prostu dodaj @JsonIgnore lub zmień nazwę metody.
Aleksiej Podlasow
1
Użyto starszej wersji:org.codehaus.jackson.annotate.JsonIgnore
AlikElzin-kilaka
6

Ten błąd jest również zgłaszany, jeśli zapomnisz dodać metodę .build () do swojego statusu zwrotu.

return Response.status(Status.OK);         // fails
return Response.status(Status.OK).build(); // works

Otrzymałem następujący błąd bez metody build ():

org.codehaus.jackson.map.JsonMappingException: No serializer found for class com.sun.jersey.core.spi.factory.ResponseBuilderImpl
patrics
źródło
4

SpringBoot2.0, rozwiązuję go, wykonując kod:

@Bean public ObjectMapper objectMapper() {
 return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);}
Janus
źródło
1
powinieneś zachować swój model z metodami getter i setter.
Janus
1
Witamy w SO! Dziękuję za pomoc. Dodaj wyjaśnienie do swojej odpowiedzi, aby było jasne, co robi kod, dlaczego działa i jak odpowiada na pytanie OP.
Max Vollmer,
To mi pomogło! Ale moim zdaniem powinieneś wstrzyknąć ObjectMapper kontekstu i skonfigurować go później, zamiast tworzyć nowy.
RoBeaToZ
3

W przypadku aplikacji Oracle Java dodaj po ObjectMapperwystąpieniu:

mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
LEMUEL ADANE
źródło
2

Miałem podobny problem z opóźnionym ładowaniem za pośrednictwem hibernowanego obiektu proxy. Obejść ten problem, dodając adnotacje do klasy, która leniwie załadowała prywatne właściwości:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
N. berouain
źródło
To rozwiązało mój problem. Czy możesz mi powiedzieć, co to dokładnie robi?
blizna
2

Problem może wynikać z zadeklarowania zmiennej jako private. Jeśli zmienisz na public, to działa.

Lepszą opcją jest użycie do tego metod pobierających i ustawiających.

To rozwiąże problem!

Sanchit Singhania
źródło
2

Znalazłem co najmniej trzy sposoby na zrobienie tego:

  1. Dodaj public gettersswój byt, który próbujesz serializować;
  2. Dodaj adnotację na górze encji, jeśli nie chcesz public getters. Spowoduje to zmianę domyślnej wartości dla Jacksona Visbility=DEFAULTna miejsce, w @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)którym akceptowane są wszelkie modyfikatory dostępu;
  3. Zmień swój ObjectMapperglobalny przez ustawienie objectMapperInstance.setVisibility(JsonMethod.FIELD, Visibility.ANY);. Należy tego unikać, jeśli nie potrzebujesz tej funkcji na całym świecie.

Wybierz w zależności od potrzeb.

George
źródło
2

Oto trzy opcje:

  1. Dane / klasy, do których uzyskano dostęp, muszą być public
  2. Jeśli nie public, dodaj pobierające i ustawiające
  3. Lub dodaj @JsonIgnore("context")
Santhosh Kumar
źródło
1

Użyj tego na poziomie klasy dla fasoli:

@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})
raveendra_bikkina
źródło
1

dodanie settera i gettera również rozwiąże problem, ponieważ został dla mnie rozwiązany. Na przykład:

public class TestA {
    String SomeString = "asd";

    public String getSomeString () {        return SomeString ;     }

    public void setSomeString (String SS ) {        SomeString = SS ;   } 
}
Satya Prakash
źródło
1

Miałem tylko gettery, po dodaniu setterów problemy zostały rozwiązane.

Vanita Dhotre
źródło
0

Chociaż dodałem pobierające i ustawiające, otrzymywałem ten sam błąd. Później znalazłem błąd, tzn. Zgodnie z radą Sonara podłączyłem programy pobierające i ustawiające jako chronione, co było przyczyną problemu. Raz ustaliłem, że działało zgodnie z oczekiwaniami.

żółty
źródło
0

w wiosennym bagażniku 2.2.5

po dodaniu gettera i setera

Dodałem @JsonIgnore na górze pola.

saba
źródło