JSON deserialization issue with Jackson and polymorphic types - Missing type id property 'type

34 Views Asked by At

I'm new to the world of programming so this could be something very simple that I'm missing. I'm facing a problem when trying to deserialize JSON using Jackson in Java. I have a VendaDTO class with a hierarchy of types (Unico product, Kit product) and I'm getting the error "Could not resolve subtype of [simple type, class com.h2healing.schedule.model.venda.VendaDTO]: missing type id property 'tipo' ". I've already tried configuring Jackson's annotations, but I still haven't been able to solve the problem. Here is the example JSON and relevant code. Any suggestions on how to resolve this?

VendaDTO

package com.h2healing.schedule.model.venda;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.h2healing.schedule.model.cliente.ClienteModel;
import com.h2healing.schedule.model.produto.InterfaceProdutoDTO;
import com.h2healing.schedule.model.produto.ProdutoKitDTO;
import com.h2healing.schedule.model.produto.ProdutoUnicoDTO;

import java.util.List;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "tipo")
@JsonSubTypes({
        @JsonSubTypes.Type(value = ProdutoUnicoDTO.class, name = "produtoUnico"),
        @JsonSubTypes.Type(value = ProdutoKitDTO.class, name = "produtoKit")
})
public record VendaDTO(
        ClienteModel cliente,
        List<InterfaceProdutoDTO> produtos,
        FormaPagamento formaDePagamento,
        String observacao) {
}

ProdutoKitDTO

package com.h2healing.schedule.model.produto;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;
@JsonTypeName("produtoKit")
public record ProdutoKitDTO(
        String codigo,
        String nomeProduto,
        String unidade,
        BigDecimal custoUnitario,
        BigDecimal valorUnitario,
        List<InterfaceProdutoDTO> produtosNoKit) implements InterfaceProdutoDTO {

    @Override
    public String getTipo() {
        return "produtoKit";
    }

    @Override
    public String getCodigo() {
        return codigo;
    }

    @Override
    public String getNomeProduto() {
        return nomeProduto;
    }

    @Override
    public String getUnidade() {
        return unidade;
    }

    @Override
    public BigDecimal getCustoUnitario() {
        return custoUnitario;
    }

    @Override
    public BigDecimal getValorUnitario() {
        return valorUnitario;
    }


    @Override
    public ProdutoModel toProdutoModel() {
        List<Composicao> composicoes = produtosNoKit.stream()
                .map(dto -> new Composicao(null, null, (ProdutoUnicoModel) dto.toProdutoModel(), BigDecimal.ZERO))
                .collect(Collectors.toList());

        ProdutoKitModel produtoKitModel = new ProdutoKitModel();
        produtoKitModel.setCodigo(codigo);
        produtoKitModel.setNomeProduto(nomeProduto);
        produtoKitModel.setUnidade(unidade);
        produtoKitModel.setCustoUnitario(custoUnitario);
        produtoKitModel.setValorVendaUnitario(valorUnitario);
        produtoKitModel.setProdutosNoKit(composicoes);

        return produtoKitModel;
    }
}

ProdutoUnicoDTO

package com.h2healing.schedule.model.produto;

import com.fasterxml.jackson.annotation.JsonTypeName;

import java.math.BigDecimal;
@JsonTypeName("produtoUnico")
public record ProdutoUnicoDTO(
        String codigo,
        String nomeProduto,
        String unidade,
        BigDecimal custoUnitario,
        BigDecimal valorUnitario,
        BigDecimal saldo
) implements InterfaceProdutoDTO{
    @Override
    public String getTipo() {
        return "produtoUnico";
    }

    @Override
    public String getCodigo() {
        return codigo;
    }

    @Override
    public String getNomeProduto() {
        return nomeProduto;
    }

    @Override
    public String getUnidade() {
        return unidade;
    }

    @Override
    public BigDecimal getCustoUnitario() {
        return custoUnitario;
    }

    @Override
    public BigDecimal getValorUnitario() {
        return valorUnitario;
    }

    public BigDecimal getSaldo() {
        return saldo;
    }

    @Override
    public ProdutoModel toProdutoModel() {
        ProdutoUnicoModel produtoUnicoModel = new ProdutoUnicoModel();
        produtoUnicoModel.setCodigo(codigo);
        produtoUnicoModel.setNomeProduto(nomeProduto);
        produtoUnicoModel.setUnidade(unidade);
        produtoUnicoModel.setCustoUnitario(custoUnitario);
        produtoUnicoModel.setValorVendaUnitario(valorUnitario);
        produtoUnicoModel.setSaldo(saldo);
        return produtoUnicoModel;
    }
}

InterfaceProdutoDTO

package com.h2healing.schedule.model.produto;

import com.fasterxml.jackson.annotation.JsonTypeInfo;

import java.math.BigDecimal;

public interface InterfaceProdutoDTO {
    String getTipo();
    String getCodigo();
    String getNomeProduto();
    String getUnidade();
    BigDecimal getCustoUnitario();
    BigDecimal getValorUnitario();
    ProdutoModel toProdutoModel();
}

JSON

{
  "cliente": {
    "id": "446f6586-9791-44d4-974f-279654b40da8",
    "nome": "Nome do Cliente"
  },
  "produtos": [
    {
      "tipo": "produtoUnico",
      "codigo": "B01",
      "nomeProduto": "Nome do Produto 2",
      "unidade": "unidade",
      "custoUnitario": 0.0,
      "valorUnitario": 0.0,
      "saldo": 0.0
    },
    {
      "tipo": "produtoKit",
      "codigo": "C03",
      "nomeProduto": "Nome do Produto 1",
      "unidade": "unidade",
      "custoUnitario": 0.0,
      "valorUnitario": 0.0,
      "produtosNoKit": [
        {
          "tipo": "produtoUnico",
          "codigo": "B02",
          "nomeProduto": "Produto no Kit",
          "unidade": "unidade",
          "custoUnitario": 0.0,
          "valorUnitario": 0.0,
          "saldo": 0.0
        }
      ]
    }
  ],
  "formaDePagamento": "DINHEIRO",
  "observacao": "Observação da venda"
}

I faced JSON deserialization issue with Jackson. Initially, I configured the @JsonTypeInfo annotation in the InterfaceProdutoDTO interface and added @JsonTypeName in the concrete classes (ProdutoUnicoDTO and ProdutoKitDTO). However, I still got the exception "Could not resolve subtype of [simple type, class com.h2healing.schedule.model.venda.VendaDTO]: missing type id property 'type'". Then I removed @JsonTypeInfo from the interface and added the getTipo() method to the concrete classes. Despite these changes, the problem persisted. I have reviewed the JSON structure and confirmed that the 'type' property is present. I'm confused about how to resolve this issue and would appreciate any guidance.

0

There are 0 best solutions below