Estou recebendo o seguinte erro ao tentar obter uma solicitação JSON e processá-la:
org.codehaus.jackson.map.JsonMappingException: nenhum construtor adequado encontrado para o tipo [tipo simples, classe com.myweb.ApplesDO]: não é possível instanciar a partir do objeto JSON (é necessário adicionar / ativar informações de tipo?)
Aqui está o JSON que estou tentando enviar:
{
"applesDO" : [
{
"apple" : "Green Apple"
},
{
"apple" : "Red Apple"
}
]
}
No Controller, tenho a seguinte assinatura de método:
@RequestMapping("showApples.do")
public String getApples(@RequestBody final AllApplesDO applesRequest){
// Method Code
}
AllApplesDO é um wrapper do ApplesDO:
public class AllApplesDO {
private List<ApplesDO> applesDO;
public List<ApplesDO> getApplesDO() {
return applesDO;
}
public void setApplesDO(List<ApplesDO> applesDO) {
this.applesDO = applesDO;
}
}
MaçãsDO:
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String appl) {
this.apple = apple;
}
public ApplesDO(CustomType custom){
//constructor Code
}
}
Eu acho que Jackson não consegue converter JSON em objetos Java para subclasses. Por favor, ajude com os parâmetros de configuração para Jackson converter JSON em objetos Java. Estou usando o Spring Framework.
EDIT: Incluído o principal erro que está causando esse problema na classe de amostra acima - Por favor, procure a resposta aceita para solução.
Respostas:
Então, finalmente, percebi qual é o problema. Não é um problema de configuração de Jackson, como eu duvidava.
Na verdade, o problema estava na classe ApplesDO :
Havia um construtor personalizado definido para a classe, tornando-o o construtor padrão. A introdução de um construtor fictício cometeu o erro de desaparecer:
fonte
Isso acontece por estes motivos:
sua classe interna deve ser definida como estática
Pode ser que você não tenha um construtor padrão em sua classe ( UPDATE: Este parece não ser o caso)
Pode ser que seus setters não estejam definidos adequadamente ou não sejam visíveis (por exemplo, setter privado)
fonte
Gostaria de adicionar outra solução a isso que não requer um construtor fictício. Como os construtores fictícios são um pouco confusos e subsequentemente confusos. Podemos fornecer um construtor seguro e, anotando os argumentos do construtor, permitimos que jackson determine o mapeamento entre o parâmetro e o campo do construtor.
então o seguinte também funcionará. Observe que a sequência dentro da anotação deve corresponder ao nome do campo.
fonte
@JsonCreator
o construtor com@JsonProperty
.Quando me deparei com esse problema, foi o resultado de tentar usar uma classe interna para servir como DO. A construção da classe interna (silenciosamente) exigia uma instância da classe anexa - que não estava disponível para Jackson.
Nesse caso, mover a classe interna para seu próprio arquivo .java corrigiu o problema.
fonte
Geralmente, esse erro ocorre porque não criamos o construtor padrão, mas, no meu caso, o problema estava ocorrendo apenas porque eu fiz a classe de objeto usada na classe pai. Isso desperdiçou meu dia inteiro.
fonte
static
.Regra de polegar : adicione um construtor padrão para cada classe que você usou como uma classe de mapeamento. Você perdeu isso e o problema surge!
Basta adicionar o construtor padrão e ele deve funcionar.
fonte
Você pode testar essa estrutura? Se bem me lembro, você pode usá-lo desta maneira:
Segundo, adicione construtor padrão a cada classe que também pode ajudar.
fonte
Você deve criar um construtor vazio simulado em nossa classe de modelo. Portanto, ao mapear json, ele é definido pelo método setter.
fonte
Se você começar a anotar o construtor, deverá anotar todos os campos.
Observe que meu campo Staff.name é mapeado para "ANOTHER_NAME" na string JSON.
fonte
Você deve perceber quais opções Jackson tem disponível para desserialização. Em Java, os nomes dos argumentos do método não estão presentes no código compilado. É por isso que Jackson geralmente não pode usar construtores para criar um objeto bem definido com tudo já definido.
Portanto, se houver um construtor vazio e também houver setters, ele usará o construtor e setters vazios. Se não houver levantadores, é usada alguma magia negra (reflexos).
Se você deseja usar um construtor com Jackson, deve usar as anotações mencionadas por @PiersyP em sua resposta. Você também pode usar um padrão de construtor. Se você encontrar algumas exceções, boa sorte. O tratamento de erros em Jackson é péssimo, é difícil entender essa tagarelice nas mensagens de erro.
fonte
Em relação à última publicação, tive o mesmo problema em que o uso do Lombok 1.18. * Gerou o problema.
Minha solução foi adicionar @NoArgsConstructor (construtor sem parâmetros), pois @Data inclui por padrão @RequiredArgsConstructor (construtor com parâmetros).
Documentação do lombok https://projectlombok.org/features/all
Isso resolveria o problema:
fonte
Falha nos serializadores / desserializadores de jackson personalizados também pode ser o problema. Embora não seja o seu caso, vale a pena mencionar.
Eu enfrentei a mesma exceção e esse foi o caso.
fonte
Para mim, isso costumava funcionar, mas a atualização das bibliotecas causou esse problema. O problema era ter uma classe como esta:
Usando o lombok:
Voltando a
Corrigido o problema. Não sei por que, mas queria documentá-lo para o futuro.
fonte