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

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() .


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.


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.


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


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)

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;

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

4

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

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

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

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"})

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!


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.


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")

1

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

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

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

1

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


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.


0

dans la botte de printemps 2.2.5

après avoir ajouté getter et setter

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.