Sérialisation avec Jackson (JSON) - obtenir "Aucun sérialiseur trouvé"?

262

J'obtiens une exception lorsque j'essaie de sérialiser un objet très simple à l'aide de Jackson. L'erreur:

org.codehaus.jackson.map.JsonMappingException: aucun sérialiseur trouvé pour la classe MyPackage.TestA et aucune propriété découverte pour créer BeanSerializer (pour éviter les exceptions, désactivez SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS))

Vous trouverez ci-dessous la classe et le code simples à sérialiser.

Quelqu'un peut-il me dire pourquoi j'obtiens cette erreur?

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();
}
Ted
la source
J'ai écrit un article sur la façon d'écrire un sérialiseur personnalisé avec Jackson qui peut être utile pour certains.
Sam Berry

Réponses:

329

Comme déjà décrit, la configuration par défaut d'une ObjectMapperinstance consiste à accéder uniquement aux propriétés qui sont des champs publics ou qui ont des getters / setters publics. Une alternative à la modification de la définition de classe pour rendre un champ public ou pour fournir un getter / setter public est de spécifier (au sous-jacent VisibilityChecker) une règle de visibilité de propriété différente. Jackson 1.9 fournit la ObjectMapper.setVisibility()méthode pratique pour le faire. Pour l'exemple de la question d'origine, je configurerais probablement ceci comme

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

Pour Jackson> 2.0:

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

Pour plus d'informations et de détails sur les options de configuration associées, je recommande de consulter les JavaDocs surObjectMapper.setVisibility() .

Programmeur Bruce
la source
59
Cela a fonctionné pour moi. Depuis Jackson 2.0, ObjectMapper # setVisibility prend un PropertyAccessor comme premier argument. L'équivalent oneliner est myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
Dan Robinson
@DanRobinson J'ai utilisé la même chose. Mais en fait, je génère un fichier yaml. donc pour le JSONString as: {"term":{"call_failed":"true"}}il génère la structure yaml comme: filter: map: term: map: call_failed: "true"Pourquoi il génère des mapmots clés? Comment puis-je le supprimer?
Manish Kumar
7
J'ai probablement passé 8 heures avec cette erreur, ne réalisant pas que ma méthode getter n'avait pas de "public" dessus ... tellement stupide
Mike Kellogg
1
Je reçois cette erreur lors de la conversion de ClientResponse en chaîne à l'aide du mappeur d'objets
VdeX
1
Vous pouvez également ajouter l'annotation @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)au-dessus de votre classe
veben
74

Pour que Jackson sérialise cette classe, le SomeStringchamp doit être public(en ce moment c'est l'isolement au niveau du package) ou vous devez définir des méthodes getter et setter pour cela.

Chris
la source
5
Veuillez noter que cette réponse est incorrecte - le champ n'a pas besoin d'être public ou d'avoir un getter et un setter. Dans une autre réponse à cette question, j'ai fourni une configuration alternative qui n'exige pas que les modifications de la structure de données d'origine soient (dé) sérialisées.
Programmeur Bruce
9
La réponse est utile, même si elle n'est pas exacte à 100%. J'avais oublié de mettre «public» sur mes vars, et cela l'a souligné. Merci!
ChrisPhoenix
54

J'ai le même problème dans mon code source. Je viens d'ajouter

getter

et

setter

le problème résolu.

Günay Gültekin
la source
1
J'ai essayé beaucoup de choses différentes, et la solution est aussi simple que cela .... et ça le dit très clairement: "aucune propriété découverte pour créer".
AKS
2
@PhilipRego Il veut dire qu'il a ajouté un getter et un setter pour le terrain.
Paul
J'utilise la bibliothèque lombok, donc j'ajoute juste une annotation Getter et Setter. Et tout allait bien. Merci.
Rahmat Hidayat
oui, les getters et setters sont utilisés pour la sérialisation de Jackson.
désérialisation
25

Le problème dans mon cas était que Jackson essayait de sérialiser un objet vide sans attribut ni méthode.

Comme suggéré dans l'exception, j'ai ajouté la ligne suivante pour éviter l'échec sur les beans vides:

Pour Jackson 1.9

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

Pour Jackson 2.X

myObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

Vous pouvez trouver un exemple simple sur jackson disable fail_on_empty_beans

Martín C
la source
9

J'ai eu le même problème pour une classe enfant où j'avais le contrôle, le mappeur d'objets était dans un module commun et était inaccessible. Je l'ai résolu en ajoutant cette annotation pour ma classe enfant dont l'objet devait être sérialisé.

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
Pavan Kumar
la source
7

Si vous pouvez modifier la classe contenant cet objet, j'ajoute généralement juste l'annotation

import com.fasterxml.jackson.annotation.JsonIgnore;

@JsonIgnore 
NonSerializeableClass obj;
ZiglioUK
la source
2
Cette erreur se déclenche également lorsque votre classe a une méthode dont le nom commence par get ... Par exemple NonSerializableClass getMyNonSerializableObject (). Jackson essaie de le sérialiser et échoue. Pour résoudre ce problème, ajoutez simplement @JsonIgnore ou renommez la méthode.
Alexey Podlasov,
1
Utilisé l'ancienne version:org.codehaus.jackson.annotate.JsonIgnore
AlikElzin-kilaka
6

Cette erreur est également levée si vous oubliez d'ajouter la méthode .build () à votre état de retour.

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

J'ai eu l'erreur suivante sans la méthode build ():

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

SpringBoot2.0 , Je le résous par le code suivant:

@Bean public ObjectMapper objectMapper() {
 return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);}
Janus
la source
1
vous devez conserver votre modèle avec des méthodes getter et setter.
Janus
1
Bienvenue chez SO! Merci d'avoir contribué. Veuillez ajouter une explication à votre réponse, afin de bien comprendre ce que fait le code, pourquoi il fonctionne et comment il répond à la question OP.
Max Vollmer
Cela m'a aidé! Mais à mon avis, vous devriez injecter l'ObjectMapper du contexte et le configurer ensuite plutôt que d'en créer un nouveau.
RoBeaToZ
3

Pour les applications Oracle Java, ajoutez ceci après l' ObjectMapperinstanciation:

mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
LEMUEL ADANE
la source
2

J'ai eu un problème similaire avec le chargement paresseux via l'objet proxy de mise en veille prolongée. Contourné en annotant la classe ayant des propriétés privées chargées paresseusement avec:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
N. berouain
la source
Cela a résolu mon problème. Pouvez-vous me dire ce que cela fait exactement?
scarface
2

Le problème peut être dû au fait que vous avez déclaré la variable en tant que private. Si vous le changez en public, cela fonctionne.

La meilleure option est d'utiliser des méthodes getter et setter pour cela.

Cela résoudra le problème!

Sanchit Singhania
la source
2

J'ai trouvé au moins trois façons de procéder:

  1. Ajoutez public gettersvotre entité que vous essayez de sérialiser;
  2. Ajoutez une annotation en haut de l'entité, si vous ne le souhaitez pas public getters. Cela va changer la valeur par défaut pour Jackson à partir Visbility=DEFAULTde @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)laquelle tous les modificateurs d'accès sont acceptés;
  3. Changez votre ObjectMappermonde en définissant objectMapperInstance.setVisibility(JsonMethod.FIELD, Visibility.ANY);. Cela devrait être évité si vous n'avez pas besoin de cette fonctionnalité à l'échelle mondiale.

Choisissez en fonction de vos besoins.

georger
la source
2

Voici les trois options:

  1. Les données / classes auxquelles vous avez accédé doivent être public
  2. Sinon public, ajoutez des getters et setters
  3. Ou ajoutez @JsonIgnore("context")
Santhosh Kumar
la source
1

Veuillez utiliser ceci au niveau de la classe pour le bean:

@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})
raveendra_bikkina
la source
1

l'ajout de setter et getter résoudra également le problème tel qu'il a été résolu pour moi. Pour Ex:

public class TestA {
    String SomeString = "asd";

    public String getSomeString () {        return SomeString ;     }

    public void setSomeString (String SS ) {        SomeString = SS ;   } 
}
Satya Prakash
la source
1

Je n'ai eu que des getters, après avoir ajouté des setters aussi, les problèmes ont été résolus.

Vanita Dhotre
la source
0

Bien que j'aie ajouté des getters et des setters, j'obtenais la même erreur. Plus tard, j'ai trouvé un bug, c'est sur les conseils de Sonar que j'ai qualifié les getters et les setters de protégés, ce qui causait le problème. Une fois que j'ai corrigé cela fonctionnait comme prévu.

Jaune
la source
0

dans la botte de printemps 2.2.5

après avoir ajouté getter et setter

j'ai ajouté @JsonIgnore au sommet du champ.

saba
la source