Serializar con Jackson (JSON): ¿aparece "No se ha encontrado ningún serializador"?

262

Recibo una excepción cuando intento serializar un objeto muy simple usando Jackson. El error:

org.codehaus.jackson.map.JsonMappingException: no se encontró un serializador para la clase MyPackage.TestA y no se descubrieron propiedades para crear BeanSerializer (para evitar excepciones, desactive SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS))

A continuación se muestra la clase simple y el código para serializar.

¿Alguien puede decirme por qué me sale este error?

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
fuente
Escribí una publicación sobre Cómo escribir un serializador personalizado con Jackson que puede ser útil para algunos.
Sam Berry

Respuestas:

329

Como ya se describió, la configuración predeterminada de una ObjectMapperinstancia es solo acceder a las propiedades que son campos públicos o tienen captadores / establecedores públicos. Una alternativa a cambiar la definición de clase para hacer público un campo o para proporcionar un captador / definidor público es especificar (al subyacente VisibilityChecker) una regla de visibilidad de propiedad diferente. Jackson 1.9 proporciona el ObjectMapper.setVisibility()método conveniente para hacerlo. Para el ejemplo en la pregunta original, probablemente configuraría esto como

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

Para Jackson> 2.0:

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

Para obtener más información y detalles sobre las opciones de configuración relacionadas, recomiendo revisar los JavaDocs enObjectMapper.setVisibility() .

Programador Bruce
fuente
59
Esto funcionó para mí. A partir de Jackson 2.0, ObjectMapper # setVisibility toma un PropertyAccessor como primer argumento. El título de línea equivalente es myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
Dan Robinson
@DanRobinson Usé lo mismo. Pero en realidad estoy generando el archivo yaml. entonces para JSONString como: {"term":{"call_failed":"true"}}está generando estructura yaml como: filter: map: term: map: call_failed: "true"¿Por qué está generando mappalabra clave? Como puedo quitarlo ?
Manish Kumar
77
Probablemente pasé 8 horas con este error, sin darme cuenta de que mi método getter no tenía "público" ... tan estúpido
Mike Kellogg
1
Recibo este error al convertir ClientResponse a cadena usando el mapeador de objetos
VdeX
1
También puede agregar la anotación @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)sobre su clase
veben
74

Para que Jackson serialice esa clase, el SomeStringcampo debe ser public(en este momento es un aislamiento a nivel de paquete) o debe definir los métodos getter y setter para él.

Chris
fuente
55
Tenga en cuenta que esta respuesta es incorrecta: el campo no necesita ser público o tener un captador y definidor. En otra respuesta a esta pregunta, proporcioné una configuración alternativa que no requiere cambios en la estructura de datos original para ser (des) serializada.
Programador Bruce
9
La respuesta es útil, incluso si no es 100% correcta. Había olvidado poner 'público' en mis vars, y esto lo señaló. ¡Gracias!
ChrisPhoenix
54

Tengo el mismo problema en mi código fuente. Acabo de agregar

adquiridor

y

setter

El problema resuelto.

Günay Gültekin
fuente
1
Intenté muchas cosas diferentes, y la solución es tan simple como esta ... y lo dice con bastante claridad: "no se descubrieron propiedades para crear".
aks
2
@PhilipRego Quiere decir que agregó un captador y un setter para el campo.
Paul
Utilizo la biblioteca lombok, así que solo agrego la anotación Getter y Setter. Y todo estuvo bien. Gracias.
Rahmat Hidayat
sí, getters y setters se utilizan para la serialización de Jackson.
deserialización
25

El problema en mi caso fue que Jackson estaba tratando de serializar un objeto vacío sin atributos ni métodos.

Como se sugiere en la excepción, agregué la siguiente línea para evitar fallas en los beans vacíos:

Para Jackson 1.9

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

Para Jackson 2.X

myObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

Puede encontrar un ejemplo simple sobre jackson disable fail_on_empty_beans

Martín C
fuente
9

Tuve el mismo problema para una clase secundaria donde tenía control, el mapeador de objetos estaba en un módulo común y era inaccesible. Lo resolví agregando esta anotación para mi clase secundaria cuyo objeto debía ser serializado.

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

Si puede editar la clase que contiene ese objeto, generalmente solo agrego la anotación

import com.fasterxml.jackson.annotation.JsonIgnore;

@JsonIgnore 
NonSerializeableClass obj;
ZiglioUK
fuente
2
Este error también se activa cuando su clase tiene un método cuyo nombre comienza con get ... Por ejemplo, NonSerializableClass getMyNonSerializableObject (). Jackson intenta serializarlo y falla. Para resolver este problema, simplemente agregue @JsonIgnore o cambie el nombre del método.
Alexey Podlasov
1
Usó la versión anterior:org.codehaus.jackson.annotate.JsonIgnore
AlikElzin-kilaka
6

Este error también se produce si olvida agregar el método .build () a su estado de retorno.

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

Obtuve el siguiente error sin el método build ():

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

SpringBoot2.0, lo resuelvo siguiendo el código:

@Bean public ObjectMapper objectMapper() {
 return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);}
Janus
fuente
1
debe mantener su modelo con métodos getter y setter.
Janus
1
Bienvenido a SO! Gracias por contribuir Agregue una explicación a su respuesta, para que quede claro qué hace el código, por qué funciona y cómo responde la pregunta de los OP.
Max Vollmer
Esto me ayudó! Pero en mi opinión, debe inyectar el ObjectMapper del contexto y configurarlo después en lugar de crear uno nuevo.
RoBeaToZ
3

Para las aplicaciones Oracle Java, agregue esto después de la ObjectMapperinstanciación:

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

Tuve un problema similar con la carga diferida a través del objeto proxy hibernate. Lo solucioné anotando la clase que tenía propiedades privadas cargadas de forma diferida con:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
N. berouain
fuente
Esto resolvió mi problema. ¿Me puede decir qué hace exactamente esto?
scarface
2

El problema puede deberse a que ha declarado la variable como private. Si lo cambia a public, funciona.

La mejor opción es utilizar métodos getter y setter para ello.

¡Esto resolverá el problema!

Sanchit Singhania
fuente
2

Encontré al menos tres formas de hacer esto:

  1. Agregue public gettersa su entidad que intenta serializar;
  2. Agregue una anotación en la parte superior de la entidad, si no lo desea public getters. Esto cambiará el valor predeterminado para Jackson a partir Visbility=DEFAULTde @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)donde se aceptan los modificadores de acceso;
  3. Cambia tu ObjectMapperconfiguración globalmente objectMapperInstance.setVisibility(JsonMethod.FIELD, Visibility.ANY);. Esto debe evitarse si no necesita esta funcionalidad a nivel mundial.

Elija según sus necesidades.

Georger
fuente
2

Aquí están las tres opciones:

  1. Los datos / clase a los que se ha accedido deben ser public
  2. Si no public, agregue captadores y establecedores
  3. O agregar @JsonIgnore("context")
Santhosh Kumar
fuente
1

Utilice esto a nivel de clase para el bean:

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

agregar setter y getter también resolverá el problema, ya que se solucionó para mí. Por ej .:

public class TestA {
    String SomeString = "asd";

    public String getSomeString () {        return SomeString ;     }

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

Solo tenía getters, después de agregar setters también, los problemas se resolvieron.

Vanita Dhotre
fuente
0

Aunque agregué getters y setters recibí el mismo error. Más tarde encontré un error, es decir, por consejo de Sonar, identifiqué a los captadores y colocadores como protegidos, lo que estaba causando el problema. Una vez que lo solucioné, funcionó como se esperaba.

amarillo
fuente
0

en la bota de primavera 2.2.5

después de agregar getter y setter

Agregué @JsonIgnore en la parte superior del campo.

saba
fuente