Can't deserialize my POJO sent from an Angular http post request on my Springboot POST mapped function

huangapple go评论76阅读模式
英文:

Can't deserialize my POJO sent from an Angular http post request on my Springboot POST mapped function

问题

以下是您要的代码部分的中文翻译:

// 这是项目的菜单项类(省略了setter和getter):
public class Menu {

    private int productId;

    private String name;

    private double price;

    private String[][] productOptions;

    private String type;

    // 这三个变量属于饮料,奶油和糖更适用于咖啡
    private String currentSize;

    private Integer creams;

    private Integer sugars;

    public Menu(int productId, String name, double price, String productOptions, String type){
        this.productId = productId;
        this.name = name;
        this.price = price;
        this.productOptions = convertOptions(productOptions);
        this.type = type;
    }

    /**
     * 用于将在数据库中由“,”分隔的键值对转换为此类中的二维数组的方法。
     * @param options
     * @return
     */
    private String[][] convertOptions(String options) {
        String[] optionPairs = options.split(",");

        // 硬编码因为我知道这些是成对的
        String retVal[][] = new String[optionPairs.length][2];

        for(int i = 0; i < optionPairs.length; ++i){
            String[] temp = optionPairs[i].split(":");
            retVal[i] =  temp;
        }

        return retVal;
    }

    @Override
    public String toString(){

        return String.format("{productId: %i, name: %s}", this.productId, this.name);
    }
}

// 这是接收请求的控制器类:
@RestController
public class OrderController {
    
    @CrossOrigin(origins = "http://localhost:4200")
    @PostMapping(path = "/guestOrder")
    public String order(@RequestBody List<Menu> order){
        
        for(Menu item: order){
            System.out.println(item.toString());
        }
        
        return "Sending order worked";
    }
}

在Angular中,菜单项的定义如下:

export interface Menu {
    productId: number;
    name: string;
    price: number;
    productOptions: string[][];
    type: string;
    currentSize: string;
    creams: number;
    sugars: number;
}

HTTP请求调用如下:

this.http.post<string>(`${this.url}/guestOrder`, this.orderItems);

如果不格式化JSON,错误会在JSON字符串的第65列发生,如下所示:

[{"productId":1,"name":"Iced Coffee","price":2,"productOptions":[["S","2.00"],["M","2.50"],["L","3.00"]],"type":"IC","currentSize":"S","creams":0,"sugars":0}]

这是在productOptions的第一个括号处发生的错误。

英文:

For context, my app is a coffee shop and I want to sent a an array of items over to my springboot backend. However jackson gives the exception:

Cannot construct instance of `me.andrewq.coffeeshop.menu_items.Menu` 
(no Creators, like default constructor, exist): cannot deserialize from Object value 
(no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 1, column: 3] (through reference chain: 
java.util.ArrayList[0])] with root cause
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 
Cannot construct instance of `me.andrewq.coffeeshop.menu_items.Menu` 
(no Creators, like default constructor, exist): cannot deserialize from Object value 
(no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 1, column: 3] (through reference chain: 
java.util.ArrayList[0]).

This is what the item's class looks like (after omitting the setters and getters):

public class Menu {
private int productId;
private String name;
private double price;
private String[][] productOptions;
private String type;
// These 3 variables belong to drinks. The creams and sugars more so for coffees
private String currentSize;
private Integer creams;
private Integer sugars;
public Menu(int productId, String name, double price, String productOptions, String type){
this.productId = productId;
this.name = name;
this.price = price;
this.productOptions = convertOptions(productOptions);
this.type = type;
}
/**
* Used for converting the product options which is a key-value pair seperated by a &#39;,&#39; in the DB, into a 2D array in this class.
* @param options
* @return
*/
private String[][] convertOptions(String options) {
String[] optionPairs = options.split(&quot;,&quot;);
//hard coded b/c I know that these are pairs 
String retVal[][] = new String[optionPairs.length][2];
for(int i = 0; i &lt; optionPairs.length; ++i){
String[] temp = optionPairs[i].split(&quot;:&quot;);
retVal[i] =  temp;
}
return retVal;
}
@Override
public String toString(){
return String.format(&quot;{productId: %i, name: %s}&quot;, this.productId, this.name);
}
}

The request is received in a controller class as:

@RestController
public class OrderController {
@CrossOrigin(origins = &quot;http://localhost:4200&quot;)
@PostMapping(path = &quot;/guestOrder&quot;)
public String order(@RequestBody List&lt;Menu&gt; order){
for(Menu item: order){
System.out.println(item.toString());
}
return &quot;Sending order worked&quot;;
}
}

In Angular the item is defined as:

export interface Menu {
productId: number;
name: string;
price: number;
productOptions: string[][];
type: string;
// additional field for drinks and coffees
currentSize: string;
creams: number;
sugars: number;
}

And the http request call is: this.http.post&lt;string&gt;(`${this.url}/guestOrder`, this.orderItems); where http: HttpClient and orderItems: Menu[].

Without formatting the JSON, error occurs at column 65 of the JSON string:

[{&quot;productId&quot;:1,&quot;name&quot;:&quot;Iced Coffee&quot;,&quot;price&quot;:2,&quot;productOptions&quot;:[[&quot;S&quot;,&quot;2.00&quot;],[&quot;M&quot;,&quot;2.50&quot;],[&quot;L&quot;,&quot;3.00&quot;]],&quot;type&quot;:&quot;IC&quot;,&quot;currentSize&quot;:&quot;S&quot;,&quot;creams&quot;:0,&quot;sugars&quot;:0}]

This is at the first bracket of productOptions

答案1

得分: 1

异常实际上已经说得很清楚 - 你需要为你的POJO类添加一个默认构造函数。

JSON解析器的工作方式是首先创建一个空实例,然后调用JSON文本中出现的每个属性的setter方法。在JSON中不包含的属性保持不变,因此具有默认构造函数分配给它的值(通常是 null,除非你将其设置为其他值)。

我希望你所说的被省略以增加清晰度的getter和setter确实存在,否则它将无法正常工作。

英文:

The exception actually says it pretty well - you need to add a default constructor to your POJO class.

The JSON parser works by first creating an empty instance and then calling the setter method for each property in encounters in the JSON text. A property that is not contained in the JSON remains untouched and therefore has the value that the default constructor assigns to it (usually null unless you set it to something else).

I hope the are getters and setters that you say are omitted for clarity, are indeed there, otherwise it won't work as well.

huangapple
  • 本文由 发表于 2020年8月19日 04:31:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/63476186.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定