2

Obviously I have a deserialization problem. I want to insert a list of new products in the db. At first I had this problem:

"trace": "org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type 
    `java.util.ArrayList<com.example.resources.entities.Product>` from Object value (token `JsonToken.START_OBJECT`); 

So i created a wrapper "ProductWrapper"

@Getter
@Setter
public class ProductWrapper implements Serializable {

    private static final long serialVersionUID = 1L;
    List<Product> products;   
}

the first problem is solved but I have another problem that I can not solve. I use a map inside the list.

 "timestamp": "2022-11-14T10:45:18.453+00:00",
    "status": 400,
    "error": "Bad Request",
    "trace": "org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.LinkedHashMap<java.lang.String,java.lang.Double>` from Array value (token `JsonToken.START_ARRAY`); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.LinkedHashMap<java.lang.String,java.lang.Double>` from Array value (token `JsonToken.START_ARRAY`)\n at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 7, column: 27] (through reference chain: com.example.resources.dto.ProductWrapperDTO[\"products\"]->java.util.ArrayList[0]->com.example.resources.entities.Product[\"dimensions\"])\r\n\tat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:391)\r\n\tat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:343)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:185)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:160)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:133)\r\n\tat org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:146)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\r\n\tat org.springframework.web.servlet.mvc.method.
@Entity
@Data
@NoArgsConstructor @AllArgsConstructor
@TypeDefs({@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)})
public class Product {

    @Id
    private String productCode;
    private String name;
    private float pricePerUnit;
    @Type(type="jsonb")
    @Column(columnDefinition = "jsonb")
    private Map<String, Double> dimensions = new HashMap<>(); 
}
@RestController
@RequestMapping("/products")
@RequiredArgsConstructor
public class ProductController {

    private ProductService productService;
    
    @PostMapping
    public void addProducts(@Valid @RequestBody ProductWrapper products) {
        productService.addProducts(products.getProducts());
    }
}
public class ProductServiceImpl implements ProductService {
    
    private ProductRepository productRepository;

    @Override
    public void addProducts(List<Product> products) {
        for (Product product : products) {
            productRepository.save(product);
        }   
    }
}

This is my request body, post in postman:

{
   "products": [
        {
            "productCode": "P100",
            "name": "produit 1",
            "pricePerUnit": "250.99",
            "dimensions": [
                {
                    "productHeight": "55",
                    "productWeight": "20"
                }
            ]
        },
         {
            "productCode": "P101",
            "name": "produit 2",
            "pricePerUnit": "250.99",
            "dimensions": [
                {
                    "productHeight": "60",
                    "productWeight": "15"
                }
            ]
        }
    ]
}

Thank you in advance for any help

1 Answer 1

2

You are getting the issue because dimensions cannot be deserialized to a map. The default based on the json you are sending is a List of a custom type (with the properties:

"productHeight": "",
"productWeight": ""

as member variables). Therefore, consider defining a custom type and storing it as a List in your entity.

Otherwise, if you really want to use a map take a look at this to define custom deserializers for that.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.