Serializzazione con Jackson (JSON): ottenere "Nessun serializzatore trovato"?


262

Ottengo l'eccezione quando provo a serializzare un oggetto molto semplice usando Jackson. L'errore:

org.codehaus.jackson.map.JsonMappingException: nessun serializzatore trovato per la classe MyPackage.TestA e nessuna proprietà trovata per creare BeanSerializer (per evitare eccezioni, disabilitare SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS))

Di seguito sono riportati la semplice classe e il codice da serializzare.

Qualcuno può dirmi perché ho questo errore?

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();
}

Ho scritto un post su Come scrivere un serializzatore personalizzato con Jackson che potrebbe essere utile per alcuni.
Sam Berry,

Risposte:


329

Come già descritto, la configurazione predefinita di ObjectMapperun'istanza è di accedere solo alle proprietà che sono campi pubblici o che hanno getter / setter pubblici. Un'alternativa alla modifica della definizione della classe per rendere pubblico un campo o per fornire un getter / setter pubblico è specificare (al sottostante VisibilityChecker) una diversa regola di visibilità della proprietà. Jackson 1.9 fornisce il ObjectMapper.setVisibility()metodo pratico per farlo. Per l'esempio nella domanda originale, probabilmente lo configurerei come

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

Per Jackson> 2.0:

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

Per ulteriori informazioni e dettagli sulle relative opzioni di configurazione, consiglio di consultare JavaDocs suObjectMapper.setVisibility() .


59
Questo ha funzionato per me. A partire da Jackson 2.0, ObjectMapper # setVisibility accetta un PropertyAccessor come primo argomento. L'equivalente oneliner è myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
Dan Robinson il

@DanRobinson Ho usato lo stesso. Ma in realtà sto generando il file yaml. quindi per JSONString come: {"term":{"call_failed":"true"}}sta generando la struttura yaml come: filter: map: term: map: call_failed: "true"Perché sta generando una mapparola chiave? Come posso rimuoverlo?
Manish Kumar,

7
Probabilmente ho trascorso 8 ore con questo errore, senza rendermi conto che il mio metodo getter non aveva "pubblico" su di esso..quindi stupido
Mike Kellogg,

1
Ricevo questo errore durante la conversione di ClientResponse in stringa usando il mappatore di oggetti
VdeX,

1
Puoi anche aggiungere l'annotazione @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)sopra la tua lezione
veben

74

Per Jackson serializzare quella classe, il SomeStringcampo deve essere public(in questo momento è l'isolamento a livello di pacchetto) oppure è necessario definire i metodi getter e setter per esso.


5
Nota che questa risposta non è corretta - il campo non deve essere pubblico o avere un getter e setter. In un'altra risposta a questa domanda, ho fornito una configurazione alternativa che non richiede che le modifiche alla struttura dati originale siano (de) serializzate.
Programmatore Bruce,

9
La risposta è utile, anche se non esattamente corretta al 100%. Avevo dimenticato di mettere "pubblico" sui miei vars e questo mi ha fatto notare. Grazie!
ChrisPhoenix,

54

Ho lo stesso problema nel mio codice sorgente. Ho appena aggiunto

procacciatore

e

setter

il problema è stato risolto.


1
Ho provato molte cose diverse e la soluzione è semplice come questa .... e lo dice abbastanza chiaramente: "nessuna proprietà scoperta da creare".
aprile

2
@PhilipRego Vuol dire che ha aggiunto un getter e setter per il campo.
Paul,

Uso la libreria lombok, quindi aggiungo semplicemente Getter e Setter di anotazione. E tutto andava bene. Grazie.
Rahmat Hidayat,

Sì, getter e setter sono usati per la serializzazione di Jackson.
Deserializzazione

25

Nel mio caso il problema era che Jackson stava cercando di serializzare un oggetto vuoto senza attributi né metodi.

Come suggerito nell'eccezione, ho aggiunto la seguente riga per evitare errori sui bean vuoti:

Per Jackson 1.9

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

Per Jackson 2.X

myObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

Puoi trovare un semplice esempio su Jackson disable fail_on_empty_beans


9

Ho avuto lo stesso problema per una classe figlio in cui avevo il controllo, il mappatore di oggetti era in un modulo comune ed era inaccessibile. L'ho risolto aggiungendo questa annotazione per la mia classe figlio il cui oggetto doveva essere serializzato.

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)

7

Se riesci a modificare la classe contenente quell'oggetto, di solito aggiungo solo l'annotazione

import com.fasterxml.jackson.annotation.JsonIgnore;

@JsonIgnore 
NonSerializeableClass obj;

2
Questo errore si attiva anche quando la tua classe ha un metodo con nome che inizia con get ... Ad esempio NonSerializableClass getMyNonSerializableObject (). Jackson prova a serializzarlo e fallisce. Per risolvere questo problema basta aggiungere @JsonIgnore o rinominare il metodo.
Alexey Podlasov,

1
Usato la versione precedente:org.codehaus.jackson.annotate.JsonIgnore
AlikElzin-Kilaka

6

Questo errore viene anche generato se si dimentica di aggiungere il metodo .build () al proprio stato di ritorno.

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

Ho ottenuto il seguente errore senza il metodo build ():

org.codehaus.jackson.map.JsonMappingException: No serializer found for class com.sun.jersey.core.spi.factory.ResponseBuilderImpl

4

SpringBoot2.0 , Lo risolvo seguendo il codice:

@Bean public ObjectMapper objectMapper() {
 return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);}

1
dovresti mantenere il tuo modello con metodi getter e setter.
Giano,

1
Benvenuti in SO! Grazie per aver contribuito. Aggiungi una spiegazione alla tua risposta, quindi è chiaro cosa fa il codice, perché funziona e come risponde alla domanda dei PO.
Max Vollmer,

Questo mi ha aiutato! Ma a mio avviso, dovresti iniettare l'ObjectMapper del contesto e configurarlo in seguito anziché crearne uno nuovo.
RoBeaToZ,

3

Per le applicazioni Oracle Java, aggiungere questo dopo l' ObjectMapperistanza:

mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

2

Ho avuto un problema simile con il caricamento lento tramite l'oggetto proxy ibernazione. Ci siamo riusciti annotando la classe con proprietà private caricate in modo pigro con:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

Questo ha risolto il mio problema. Puoi dirmi cosa fa esattamente questo?
scarface

2

Il problema potrebbe essere dovuto al fatto che hai dichiarato variabile come private. Se lo cambi public, funziona.

Un'opzione migliore è usare i metodi getter e setter per questo.

Questo risolverà il problema!


2

Ho trovato almeno tre modi per farlo:

  1. Aggiungi public gettersalla tua entità che provi a serializzare;
  2. Aggiungi un'annotazione nella parte superiore dell'entità, se non lo desideri public getters. Questo cambierà il valore predefinito per Jackson da Visbility=DEFAULTa @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)cui si accettano eventuali modificatori di accesso;
  3. Cambia il tuo ObjectMapperglobalmente impostando objectMapperInstance.setVisibility(JsonMethod.FIELD, Visibility.ANY);. Questo dovrebbe essere evitato se non si necessita di questa funzionalità a livello globale.

Scegli in base alle tue esigenze.


2

Ecco le tre opzioni:

  1. I dati / la classe a cui è stato effettuato l'accesso devono essere public
  2. In caso contrario public, aggiungi getter e setter
  3. Oppure aggiungi @JsonIgnore("context")

1

Utilizzare questo a livello di classe per il bean:

@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})

1

l'aggiunta di setter e getter risolverà anche il problema risolto per me. Per esempio:

public class TestA {
    String SomeString = "asd";

    public String getSomeString () {        return SomeString ;     }

    public void setSomeString (String SS ) {        SomeString = SS ;   } 
}

1

Ho avuto solo getter, dopo aver aggiunto anche setter, i problemi risolti.


0

Sebbene avessi aggiunto getter e setter, stavo ottenendo lo stesso errore. Più tardi ho trovato un bug, che è il consiglio di Sonar che ho protetto i getter e i setter come protetti che stava causando il problema. Una volta ho risolto che ha funzionato come previsto.


0

in avvio a molla 2.2.5

dopo aver aggiunto getter e setter

ho aggiunto @JsonIgnore in cima al campo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.