从@Requestbody获取空值



我正在将DTO层添加到一个安静的api中。以前,程序直接使用实体(配方和成分),现在我在两者之间添加了一个新的 DTO 层(配方DTO 成分DTO)。但是,当我进行更改的那一刻,我开始从@RequestBody中获取 Null 值。每个配方都包含一个成分列表,它是返回空值的成分列表,配方本身返回正常。

控制器看起来像这样

package com.example.recipes.controller;
import com.example.recipes.DTO.RecipeDTO;
import com.example.recipes.Service.RecipeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/*...*/
@PostMapping(path = "/post")
public void postRecipes(@RequestBody RecipeDTO recipeDTO){
recipeService.postRecipes(recipeDTO);
}
/*...*/

配方实体

package com.example.recipes.Entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.List;
@Data
@Entity
@Table(name = "recipe", schema = "public")
@AllArgsConstructor
@NoArgsConstructor
public class Recipe {
@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
@Column(name = "id", updatable = false, nullable = false)
private long id;
@Column(name = "name")
private String name;
@Column(name = "instructions")
private String instructions;
@OneToMany(mappedBy = "recipe")
private List<Ingredient> ingredients;
@JsonProperty("date_added")
private String dateAdded = String.valueOf(LocalDateTime.now());
@JsonProperty("last_edited")
private String lastEdited = String.valueOf(LocalDateTime.now());
}

配方DTO

package com.example.recipes.DTO;
import lombok.*;
import javax.persistence.OneToMany;
import java.time.LocalDateTime;
import java.util.List;
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
public class RecipeDTO {
private long id;
private String name;
private String instructions;
private List<IngredientDTO> ingredientsDTO;
private String dateAdded = String.valueOf(LocalDateTime.now());
private String lastEdited = String.valueOf(LocalDateTime.now());
public RecipeDTO(long id, String name, String instructions, String dateAdded, String lastEdited) {
this.id = id;
this.name = name;
this.instructions = instructions;
this.dateAdded = dateAdded;
this.lastEdited = lastEdited;
}
}

成分实体

package com.example.recipes.Entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import javax.persistence.*;
@Data
@Entity
@Table(name = "Ingredient")
@NoArgsConstructor
public class Ingredient {
@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
@JsonProperty("ingredient_id")
private long ingredient_ID;
@JsonProperty("ingredient_name")
private String ingredientName;
@Column(name = "amount")
private int amount;
@Column(name = "unit")
private String unit;
@ManyToOne
@JoinColumn(name = "recipe_id")
@ToString.Exclude
@JsonIgnore
private Recipe recipe;
}

成分目录

package com.example.recipes.DTO;
import lombok.*;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class IngredientDTO {
private long ingredientID;
private String ingredientName;
private int amount;
private String unit;
}

我发送的 JSON

{
"name":"unique2",
"ingredients":[
{
"ingredient_name":"Atlantic",
"amount":13, 
"unit":"ton"
},
{
"ingredient_name":"Pacific",
"amount":15, 
"unit":"boatload"
},
{
"ingredient_name":"Indian",
"amount":38, 
"unit":"trucload"
}
],
"instructions":"easy on the salt"
}

并且成分DTO@requestbody为零

this is recipe: RecipeDTO(id=0, name=unique2, instructions=easy on the salt, ingredientsDTO=null, dateAdded=2022-08-08T15:04:10.678748100, lastEdited=2022-08-08T15:04:10.678748100)

编辑:我刚刚尝试从实体类中复制代码并将它们粘贴到 DTO 类中,它仍然返回 null...

package com.example.recipes.DTO;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.List;
@Data
@Entity
@Table(name = "recipe", schema = "public")
@AllArgsConstructor
@NoArgsConstructor
public class RecipeDTO {
@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
@Column(name = "id", updatable = false, nullable = false)
private long id;
@Column(name = "name")
private String name;
@Column(name = "instructions")
private String instructions;
@OneToMany(mappedBy = "recipeDTO")
private List<IngredientDTO> ingredientDTOs;
@JsonProperty("date_added")
private String dateAdded = String.valueOf(LocalDateTime.now());
@JsonProperty("last_edited")
private String lastEdited = String.valueOf(LocalDateTime.now());
public RecipeDTO(long id, String name, String instructions, String dateAdded, String lastEdited) {
this.id = id;
this.name = name;
this.instructions = instructions;
this.dateAdded = dateAdded;
this.lastEdited = lastEdited;
}
}
package com.example.recipes.DTO;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import javax.persistence.*;
@Data
@Entity
@Table(name = "Ingredient")
@NoArgsConstructor
public class IngredientDTO {
@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
@JsonProperty("ingredient_id")
private long ingredientID;
@JsonProperty("ingredient_name")
private String ingredientName;
@Column(name = "amount")
private int amount;
@Column(name = "unit")
private String unit;
@ManyToOne
@JoinColumn(name = "recipe_id")
@ToString.Exclude
@JsonIgnore
private RecipeDTO recipeDTO;
public IngredientDTO(long ingredientID, String ingredientName, int amount, String unit) {
this.ingredientID = ingredientID;
this.ingredientName = ingredientName;
this.amount = amount;
this.unit = unit;
}
}

@RequestBody

this is recipe: RecipeDTO(id=0, name=unique2, instructions=easy on the salt, ingredientDTOs=null, dateAdded=2022-08-08T15:24:19.325806500, lastEdited=2022-08-08T15:24:19.325806500)
these are the ingredients: null
this is ingredientDTO: null
this is ingredientDTO: null

编辑2:我尝试只发布成分DTO,@RequestBody能够很好地拿起它

//this is fine
public void testRecipePost(@RequestBody IngredientDTO ingredientDTO) {
System.out.println("ingredientDTO: " + ingredientDTO);
}

你可以替换

@OneToMany(mappedBy = "recipeDTO")
private List<IngredientDTO> ingredientDTOs;

@OneToMany(mappedBy = "recipeDTO")
private List<IngredientDTO> ingredients;

或添加

@JsonProperty("ingredients")

例:

@JsonProperty("ingredients")
@OneToMany(mappedBy = "recipeDTO")
private List<IngredientDTO> ingredientDTOs;

null的原因是因为 Jackson 不知道如何使用不同的名称正确反序列化您的字段。

在 json 中,名称是ingredients,但在 DTO 中,它是ingredientsDTO。这 2 个需要匹配。

您请求

{
"name":"unique2",
"ingredients":[...]

在这里,您在 JSON 中传递的数组名称在您使用的实体中是不同的。

您的 DTO

@OneToMany(mappedBy = "recipeDTO")
private List<IngredientDTO> ingredientDTOs;

JSON 请求和实体中的字段名称必须匹配。

将字段private List<IngredientDTO> ingredientDTOs;的名称更改为ingredients