Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Erro retorno JSON

Boa tarde pessoal da Alura!

Estou fazendo um backend para estudo, a temática do meu projeto é ser um "ifood"... Enfim, estou desenvolvendo um fix para corrigir algumas coisas no método POST para criar um pedido e toda vez que mando uma requisição no postman estou recebendo essa exception:

"message": "JSON parse error: Cannot deserialize value of type `java.lang.Long` from Object value (token `JsonToken.START_OBJECT`); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.lang.Long` from Object value (token `JsonToken.START_OBJECT`)\n at [Source: (PushbackInputStream); line: 5, column: 6] (through reference chain: br.com.develfoodspringweb.develfoodspringweb.controller.form.RequestForm[\"platesId\"]->java.util.ArrayList[0])",

A minha classe RequestForm é o seguinte:

package br.com.develfoodspringweb.develfoodspringweb.controller.form;

import br.com.develfoodspringweb.develfoodspringweb.models.Plate;
import br.com.develfoodspringweb.develfoodspringweb.models.StatusRequest;
import br.com.develfoodspringweb.develfoodspringweb.models.User;
import br.com.develfoodspringweb.develfoodspringweb.models.Request;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import javax.validation.constraints.NotNull;
import java.util.List;

/**
 * Created By Luis Gregorio
 *
 * Class created to collect information from the application and send it to the API
 */
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class RequestForm {

    private Long id;
    private StatusRequest status;
    @NotNull
    private String obs;
    private User user;
    private Long restaurantId;
    private List<Long> platesId;
    private List<Plate> plates;
    private int quantity;

    public Request convertToUserRequest (RequestForm requestForm){
        return new Request(requestForm);
    }
}

a minha classe RequestDto:

package br.com.develfoodspringweb.develfoodspringweb.controller.dto;

import br.com.develfoodspringweb.develfoodspringweb.models.Plate;
import br.com.develfoodspringweb.develfoodspringweb.models.Request;
import br.com.develfoodspringweb.develfoodspringweb.models.StatusRequest;
import br.com.develfoodspringweb.develfoodspringweb.models.User;
import com.fasterxml.jackson.annotation.JsonIgnore;
import br.com.develfoodspringweb.develfoodspringweb.models.StatusRequest;
import br.com.develfoodspringweb.develfoodspringweb.models.User;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@NoArgsConstructor
public class RequestDto {

    private Long id;
    private StatusRequest status;
    private User user;
    private String dateRequest;
    private List<PlateDto> plateDtos;
    private String obs;
    private Double priceTotal;
    @JsonIgnore
    private List<Plate> plates;

    public RequestDto(Request request){
        this.id = request.getId();
        this.status = request.getStatus();
        this.dateRequest = request.getDateRequest();
        this.user = request.getUser();
        this.obs = request.getObs();
        this.priceTotal = request.getPriceTotal();
        this.plates = request.getPlateId();
        this.converToListDto(request.getPlateId());
    }


    /**
     * Function to convert PlateModel class, receveid when creating a request, to a list of DTO class which is called from the constructor above in this class
     * @param plates
     * @return
     * @author: Thomas Benetti
     */
    private void converToListDto(List<Plate> plates) {
        if(this.plateDtos == null){
            this.plateDtos = new ArrayList<>();
        }
        plates.stream().forEach(plate -> this.plateDtos.add(new PlateDto(plate)));
    }

    /**
     * Function to convert Model class to a list of DTO class
     * @param request
     * @return
     * @author: Thomas Benetti
     */
    public static RequestDto convertToRequestDto (Request request){
        return new RequestDto(request);
    }
}
4 respostas

Classe RequestService

/**
 * Created By Luis Gregorio
 *
 * Service created to implement the search method in the controller.
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class RequestService {

  //injeções de dependência

    /**
     * Function to create new request from the current user logged in
     * @param requestForm
     * @return
     * @author: Thomas Benetti
     */
    public RequestDto registerRequest(RequestForm requestForm, PlateForm plateForm) {
        Optional<Restaurant> idRestaurants = restaurantRepository.findById(requestForm.getRestaurantId());
        if (idRestaurants.isPresent()) {
            requestForm.getPlatesId().forEach(pp -> {
                var valid = idRestaurants.get().getPlates().stream().anyMatch(plate -> plate.getId().equals(pp.longValue()));
                        if(!valid) {
                            throw new ApiExceptionError("It is impossible to create a request with plates from other restaurants");
                        }
            });
            Request request = requestForm.convertToUserRequest(requestForm);
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String currentUserAuth = authentication.getName();
            Optional<User> currentUser = userRepository.findByEmail(currentUserAuth);
            if (!currentUser.isPresent()) {
                return null;
            }

            List<Plate> platesFromRequest = plateRepository.findAllById(requestForm.getPlatesId());
            if (platesFromRequest.isEmpty()) {
                return null;
            }
            request.setPlateId(platesFromRequest);

            platesFromRequest.stream().forEach(pl -> {
                Double preco = request.getPriceTotal() + pl.getPrice();
                request.setPriceTotal(preco);
            });

            platesFromRequest.stream().forEach(q -> {
                int quantity = request.getQuantity() + q.getQuantity();
                request.setQuantity(quantity);
            });

            request.setUser(currentUser.get());
            requestRepository.save(request);

            RequestDto requestDto = new RequestDto(request);
            requestDto.setUser(null);

            return requestDto;
        }
        return null;
    }

    /**
     * Search method using the service query to be used in the Controller class
     * @param id
     * @return
     * @author: Luis Gregorio
     */
    public RequestDto searchRequestId(Long id) {
        Request request = requestRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Request not found"));
        RequestDto dto = new RequestDto();
        dto.setPlates(request.getPlateId());
        BeanUtils.copyProperties(request, dto);
        return dto;
    }

    /**
     * Method created to use the attributes coming from the Present classes,
     * setting and simplifying the information in the request body
     *
     * @param dto
     * @return
     * @author: Luis Gregorio
     */
    public RequestPresent convertToPresent(RequestDto dto) {
        RequestPresent present = new RequestPresent();
        present.setId(dto.getId());
        present.setStatus(dto.getStatus());
        present.setObs(dto.getObs());
        present.setDateRequest(dto.getDateRequest());

        List<PlatePresent> platePresents = new ArrayList<>();
        dto.getPlates().forEach(plates ->{
            PlatePresent platePresent = new PlatePresent();
            platePresent.setName(plates.getName());
            platePresent.setDescription(plates.getDescription());
            platePresent.setPrice(plates.getPrice());
            platePresent.setQuantity(plates.getQuantity());
            platePresent.setCategory(plates.getCategory());
            platePresents.add(platePresent);
        });

        UserPresent userPresent = new UserPresent();
        userPresent.setName(dto.getUser().getName());
        userPresent.setAddress(dto.getUser().getAddress());
        userPresent.setCpf(dto.getUser().getCpf());
        userPresent.setEmail(dto.getUser().getEmail());
        userPresent.setPhone(dto.getUser().getPhone());
        present.setUser(userPresent);
        present.setPlates(platePresents);

        return present;
    }

 //Mais métodos da classe Present...
}

Em uma breve pesquisa, descobri que estou com o JSON igual ao meu objeto que estou recebendo, mas estou com um pouco de dificuldade em desenvolver uma resolução. Alguém teria uma dica?

Desde já muito obrigado :D

Complementando o corpo do meu JSON enviado:

{
    "restaurantId":3,
    "platesId":
    [
        {
            "id":5,
            "quantity":1,
            "obs":"obs teste"
        },
        {
            "id":6,
            "quantity":1,
            "obs":"obs teste"
        }
    ]
}
solução!

Reformulei o meu método de registrar um novo prato e funcionou.

    /**
     * Function to create new request from the current user logged in
     * @param requestForm
     * @return
     * @author: Thomas Benetti
     */
    public RequestDto registerRequest(RequestForm requestForm) {
        Optional<Restaurant> idRestaurants = restaurantRepository.findById(requestForm.getRestaurantId());
        if (idRestaurants.isPresent()) {
            requestForm.getPlatesId().forEach(pp -> {
                var valid = idRestaurants.get().getPlates().stream().anyMatch(plate -> plate.getId().equals(pp.getId()));
                        if(!valid) {
                            throw new ApiExceptionError("It is impossible to create a request with plates from other restaurants");
                        }
            });

            Request request = requestForm.convertToUserRequest(requestForm);
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String currentUserAuth = authentication.getName();
            Optional<User> currentUser = userRepository.findByEmail(currentUserAuth);
            if (!currentUser.isPresent()) {
                return null;
            }

            List<Plate> listPlate = new ArrayList<>();
            List<PlateDto> listPlateDto = new ArrayList<>();
            plateManipulation(requestForm, request, listPlate, listPlateDto);

            request.setPlateId(listPlate);

            request.setUser(currentUser.get());
            requestRepository.save(request);

            RequestDto requestDto = new RequestDto(request);
            requestDto.setPlateDtos(listPlateDto);
            requestDto.setUser(null);

            return requestDto;
        }
        return null;
    }

    /**
     * Refactored method for returning the DTO in the create request.
     * This method aims to show the quantity of products as well as their sum, adding a final sum to the request.
     *
     * @param requestForm
     * @param request
     * @param listPlate
     * @param listPlateDto
     * @author: Luis Gregorio
     */
    private void plateManipulation(RequestForm requestForm, Request request, List<Plate> listPlate, List<PlateDto> listPlateDto) {
        requestForm.getPlatesId().forEach(vl ->{
            Optional<Plate> platesFromRequest = plateRepository.findById(vl.getId());
            PlateDto plateDto = new PlateDto();
            plateDto.setPhoto(platesFromRequest.get().getPhoto());
            plateDto.setId(platesFromRequest.get().getId());
            plateDto.setName(platesFromRequest.get().getName());
            plateDto.setDescription(platesFromRequest.get().getDescription());
            plateDto.setPrice(platesFromRequest.get().getPrice());
            plateDto.setCategory(platesFromRequest.get().getCategory());
            plateDto.setQuantity(vl.getQuantity());
            plateDto.setRestaurantName(platesFromRequest.get().getRestaurant().getName());

            if (platesFromRequest.isPresent()) {
                Double priceTotal = vl.getQuantity() * platesFromRequest.get().getPrice();
                Double preco = request.getPriceTotal() + priceTotal;
                plateDto.setPriceTotal(priceTotal);
                request.setPriceTotal(preco);
            }
            listPlate.add(platesFromRequest.get());
            listPlateDto.add(plateDto);
        });
    }