Serializando com Jackson (JSON) - recebendo “Nenhum serializador encontrado”?

262

Recebo uma exceção ao tentar serializar um objeto muito simples usando Jackson. O erro:

org.codehaus.jackson.map.JsonMappingException: nenhum serializador encontrado para a classe MyPackage.TestA e nenhuma propriedade descoberta para criar BeanSerializer (para evitar exceção, desative SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS))

Abaixo está a classe e o código simples para serializar.

Alguém pode me dizer por que recebo esse erro?

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
fonte
Eu escrevi um post sobre Como escrever um serializador personalizado com Jackson, que pode ser útil para alguns.
Sam Berry

Respostas:

329

Como já descrito, a configuração padrão de uma ObjectMapperinstância é acessar apenas propriedades que são campos públicos ou têm getters / setters públicos. Uma alternativa para alterar a definição de classe para tornar um campo público ou fornecer um getter / setter público é especificar (para o subjacente VisibilityChecker) uma regra de visibilidade de propriedade diferente. Jackson 1.9 fornece o ObjectMapper.setVisibility()método de conveniência para fazer isso. Para o exemplo da pergunta original, eu provavelmente configuraria isso como

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

Para Jackson> 2.0:

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

Para obter mais informações e detalhes sobre opções de configuração relacionadas, recomendo revisar os JavaDocsObjectMapper.setVisibility() .

Programador Bruce
fonte
59
Isso funcionou para mim. A partir do Jackson 2.0, o ObjectMapper # setVisibility usa um PropertyAccessor como o primeiro argumento. O oneliner equivalente é myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
Dan Robinson
@ DanRobinson eu usei o mesmo. Mas, na verdade, estou gerando arquivo yaml. assim, para o JSONString como: {"term":{"call_failed":"true"}}está gerando estrutura yaml como: filter: map: term: map: call_failed: "true"Por que está gerando mappalavra-chave? Como posso removê-lo?
precisa saber é o seguinte
7
Eu provavelmente passou 8 horas com este erro, não percebendo que meu método getter não têm "público" na it..so estúpido
Mike Kellogg
1
Estou recebendo este erro durante a conversão ClientResponse a string usando mapeador de objeto
VdeX
1
Você também pode adicionar a anotação @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)acima da sua classe
veben
74

Para Jackson serializar essa classe, o SomeStringcampo precisa ser public(agora é isolamento no nível do pacote) ou você precisa definir métodos getter e setter para ela.

Chris
fonte
5
Observe que esta resposta está incorreta - o campo não precisa ser público ou ter um getter e um setter. Em outra resposta a essa pergunta, forneci uma configuração alternativa que não exige que as alterações na estrutura de dados original sejam (des) serializadas.
Programador Bruce
9
A resposta é útil, mesmo que não seja 100% correta. Eu tinha esquecido de colocar 'público' nos meus vars, e isso apontou isso. Obrigado!
ChrisPhoenix
54

Eu tenho o mesmo problema no meu código fonte. Acabei de adicionar

getter

e

normatizador

o problema resolvido.

Günay Gültekin
fonte
1
Tentei muitas coisas diferentes, e a solução é tão simples quanto isso .... e diz claramente: "nenhuma propriedade descoberta para criar".
aks
2
@PhilipRego Ele quer dizer que ele adicionou um getter e um setter para o campo.
Paul
Eu uso a biblioteca lombok, então apenas adiciono anotação Getter e Setter. E estava tudo bem. Obrigado.
Rahmat Hidayat
Sim, getters e setters são usados ​​para serialização de Jackson. / desserialização
Ikhiloya Imokhai
25

O problema no meu caso foi que Jackson estava tentando serializar um objeto vazio sem atributos nem métodos.

Conforme sugerido na exceção, adicionei a seguinte linha para evitar falhas nos beans vazios:

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

Você pode encontrar um exemplo simples em jackson disable fail_on_empty_beans

Martín C
fonte
9

Eu tive o mesmo problema para uma classe filho em que eu tinha controle, o mapeador de objetos estava em um módulo comum e estava inacessível. Eu o resolvi adicionando esta anotação para minha classe filho cujo objeto deveria ser serializado.

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

Se você pode editar a classe que contém esse objeto, geralmente adiciono a anotação

import com.fasterxml.jackson.annotation.JsonIgnore;

@JsonIgnore 
NonSerializeableClass obj;
ZiglioUK
fonte
2
Este erro é acionado também quando sua classe possui um método com o nome começando com get ... Por exemplo NonSerializableClass getMyNonSerializableObject (). Jackson tenta serializar e falha. Para resolver esse problema, adicione @JsonIgnore ou renomeie o método.
Alexey Podlasov
1
Usou a versão mais antiga:org.codehaus.jackson.annotate.JsonIgnore
AlikElzin-kilaka 6/16
6

Este erro também é gerado se você esquecer de adicionar o método .build () ao seu status de retorno.

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

Eu recebi o seguinte erro sem o método build ():

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

SpringBoot2.0 , Eu resolvo isso seguindo o código:

@Bean public ObjectMapper objectMapper() {
 return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);}
Janus
fonte
1
você deve manter seu modelo com métodos getter e setter.
Janus
1
Bem-vindo ao SO! Obrigado por contribuir. Adicione uma explicação à sua resposta, para que fique claro o que o código faz, por que funciona e como responde à pergunta do OP.
precisa saber é o seguinte
Isso me ajudou! Mas, na minha opinião, você deve injetar o ObjectMapper do contexto e configurá-lo posteriormente, em vez de criar um novo.
RoBeaToZ 28/08/19
3

Para aplicativos Oracle Java, adicione isso após a ObjectMapperinstanciação:

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

Eu tive um problema semelhante com o carregamento lento por meio do objeto proxy hibernar. Para contornar isso, anotando a classe com propriedades particulares carregadas preguiçosamente com:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
N. berouain
fonte
Isso resolveu meu problema. Você pode me dizer o que isso faz exatamente?
scarface
2

O problema pode ser porque você declarou a variável como private. Se você mudar parapublic , ele funciona.

A melhor opção é usar métodos getter e setter para isso.

Isso resolverá o problema!

Sanchit Singhania
fonte
2

Encontrei pelo menos três maneiras de fazer isso:

  1. Adicione public gettersà sua entidade que você tenta serializar;
  2. Adicione uma anotação na parte superior da entidade, se você não quiser public getters. Isso mudará o padrão para Jackson de Visbility=DEFAULTpara@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) onde os modificadores de acesso são aceitos;
  3. Mude o seu ObjectMapperglobalmente, definindo objectMapperInstance.setVisibility(JsonMethod.FIELD, Visibility.ANY);. Isso deve ser evitado se você não precisar dessa funcionalidade globalmente.

Escolha com base nas suas necessidades.

georger
fonte
2

Aqui estão as três opções:

  1. Os dados / classes acessados ​​precisam ser public
  2. Caso contrário public, adicione getters e setters
  3. Ou adicione @JsonIgnore("context")
Santhosh Kumar
fonte
1

Por favor, use isso no nível da classe para o bean:

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

adicionar setter e getter também resolverá o problema que foi corrigido para mim. Para Ex:

public class TestA {
    String SomeString = "asd";

    public String getSomeString () {        return SomeString ;     }

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

Eu só tinha getters, depois de adicionar setters também, os problemas foram resolvidos.

Vanita Dhotre
fonte
0

Embora eu tenha adicionado getters e setters, estava recebendo o mesmo erro. Mais tarde, encontrei um bug, ou seja, seguindo o conselho do Sonar, selecionei os getters e setters como protegidos, o que estava causando o problema. Uma vez consertei que funcionava como esperado.

amarelo
fonte
0

na bota com mola 2.2.5

depois de adicionar getter e setter

Adicionei @JsonIgnore no topo do campo.

saba
fonte