Can not deserialize instance of java.util.ArrayList out of START_OBJECT token

0

Using angular, I am not able to insert an array of genres into the Gender property that is in the Manga object.

Using postman to insert the Generos array into the API / manga would look like this.

    {
    "nome": "BORUTO",
    "status": "COMPLETO",
    "dataLancado": "2015",
    "genero" : [{"id":1, "nome":"TERROR"},{"id":"2", "nome":"ACAO"}]
   }

Postman manga api

I tried the following way using checkbox but I got an error.

index.html

   <label ng-repeat="genero in generolist ">
        <input type="checkbox" checklist-model="selected.generos" checklist-value="genero" ng-model="manga.genero[selected.generos.id]"/> {{genero.nome}}
     </label>
     <pre>{{selected.generos|json}}</pre>     

    <input type="button" value="Salvar" ng-click="salvarMangas()"/>

Error.

2017-11-20 13:18:07.146  WARN 4324 --- [nio-8080-exec-9] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
 at [Source: java.io.PushbackInputStream@659aad31; line: 1, column: 11] (through reference chain: com.mangastech.model.MangasEntity["genero"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
 at [Source: java.io.PushbackInputStream@659aad31; line: 1, column: 11] (through reference chain: com.mangastech.model.MangasEntity["genero"])
2017-11-20 13:18:07.147  WARN 4324 --- [nio-8080-exec-9] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
 at [Source: java.io.PushbackInputStream@659aad31; line: 1, column: 11] (through reference chain: com.mangastech.model.MangasEntity["genero"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
 at [Source: java.io.PushbackInputStream@659aad31; line: 1, column: 11] (through reference chain: com.mangastech.model.MangasEntity["genero"])

mangas-controller.js

        $scope.mangas = [];
        $scope.manga = {};
        $scope.generolist = [
                {id:1, nome: 'TERROR'}
        ];

        $scope.selected = {
                generos : []
        };

        $scope.salvarMangas= function() {
            $http({
                  method: 'POST', url: 'http://localhost:8080/manga',data:$scope.manga})
                  .then(function (response) {
                    $scope.mangas.push(response.data);
                     /*carregarClientes();

                      $scope.manga={};*/

                  }, function (response) {
                    console.log(response.data);
                    console.log(response.status);
                  });
            };

MangasController in java.

//Cadastra novo Manga
    @RequestMapping(value="/manga", method=RequestMethod.POST)
    public MangasEntity cadastrarManga(@Valid @RequestBody MangasEntity manga){
        return mangaRepository.save(manga);
    }

MangasEntity.class

public class MangasEntity implements Serializable {

    private static final long serialVersionUID = 1L;
    private Long id;
    private String nome;
    private  Status status;
    private int dataLancado;

    @JsonIgnoreProperties("manga")  
    private  AutorEntity autor;

    private List<GenerosEntity> genero = new ArrayList<>();

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name="nome")
    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @Enumerated(EnumType.STRING)
    @Column(name="status")
    public Status getStatus() {
        return status;
    }


    public void setStatus(Status status) {
        this.status = status;
    }

    @Column
    public int getDataLancado() {
        return dataLancado;
    }

    public void setDataLancado(int dataLancado) {
        this.dataLancado = dataLancado;
    }

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinTable(name="mangas_autor",
    joinColumns=@JoinColumn(name="manga_id",referencedColumnName="id"),
    inverseJoinColumns = @JoinColumn(name="autor_id",referencedColumnName="id"))

    public AutorEntity getAutor() {
        return autor;
    }

    public void setAutor(AutorEntity autor) {
        this.autor = autor;
    }


    @ManyToMany(targetEntity = GenerosEntity.class)
    @JoinTable(name="mangas_generos", 
    joinColumns=@JoinColumn(name="manga_id", referencedColumnName="id"),
    inverseJoinColumns=@JoinColumn(name="genero_id", referencedColumnName="id")
    )

    public List<GenerosEntity> getGenero() {
        return this.genero;
    }


    public void setGenero(List<GenerosEntity> genero) {
        this.genero = genero;
    }

    public MangasEntity() {
        super();
    }


    public MangasEntity(Long id, String nome, Status status, int dataLancado, AutorEntity autor,
            List<GenerosEntity> genero) {
        super();
        this.id = id;
        this.nome = nome;
        this.status = status;
        this.dataLancado = dataLancado;
        this.autor = autor;
        this.genero = genero;
    }

    public MangasEntity(Long id){
        this.id = id;
    }
}

GenerosEntity.class

public class GenerosEntity implements Serializable {    


    private static final long serialVersionUID = 1L;
    private Long id;
    private String nome;

    @JsonIgnore
    private List<MangasEntity> manga  ;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name="nome")
    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @ManyToMany(mappedBy="genero", cascade = CascadeType.ALL, fetch = FetchType.EAGER)  
    public List<MangasEntity> getManga() {
        return manga;
    }

    public void setManga(List<MangasEntity> manga) {
        this.manga = manga;
    }

    public GenerosEntity() {

    }

    public GenerosEntity(Long id) {
            this.id = id;
    }

}
    
asked by anonymous 20.11.2017 / 16:31

1 answer

2

I believe the source of the error is the format of the object you are sending to API. I made a sample code where all GENEROS are first fetched to load the list of checkboxes, then the MANGA is edited to go through the list genres marking those already linked to the manga and each change of the checkboxes the list of manga genres being edited will be updated.

controller.js

.controller('indexController',['$scope','$filter', function($scope, $filter){
    var vm = this;
    vm.Model={};

    //Aqui vem a chamada da API dos generos
    vm.Model.Generos=[
        {
            "id": 1,
            "nome": "TERROR"
        },
        {
            "id": 2,
            "nome": "ACAO"
        },
        {
            "id": 3,
            "nome": "AVENTURA"
        },
        {
            "id": 4,
            "nome": "ROMANCE"
        }
    ];
    //no sucesso da requisição ele chama o manga

    //Aqui vem API de obter o Manga que preencherá o item par edição
    vm.Model.Manga = {
        "nome": "BORUTO",
        "status": "COMPLETO",
        "dataLancado": "2015",
        "genero" : [{"id":1, "nome":"TERROR"},{"id":"2", "nome":"ACAO"}]
    };

    //no then do manga ele executa e atualiza a lista de generos
    vm.Load= function (){
        if (vm.Model.Manga.genero && vm.Model.Generos) {
            angular.forEach(vm.Model.Generos, function(_genero, i){
                _genero.Selecionado = $filter('filter')(vm.Model.Manga.genero,{id:_genero.id}).length > 0 ;         
            });
        };
    }
    vm.Load();

    //função após mudar os checkboxes
    vm.Selecionar = function () {
        vm.Model.Manga.genero = $filter('filter')(vm.Model.Generos,{Selecionado: true});
    }

}]);

view.html

<legend>Form title</legend>
<hr/>
<div class="form-group">
    <label for="">Nome</label>
    <input ng-model="vm.Model.Manga.nome" class="form-control" type="text">
</div>
<div class="form-group">
    <label for="">Status</label>
    <input ng-model="vm.Model.Manga.status" class="form-control" type="text">
</div>
<div class="form-group">
 <ul>
     <li ng-repeat="_genero in vm.Model.Generos">
         <label>
             <input ng-model="_genero.Selecionado"
                    ng-change="vm.Selecionar()"
                    type="checkbox" />
             <span ng-bind="_genero.nome"></span>                       
         </label>
     </li>
 </ul> 
</div>  
    
23.11.2017 / 02:32