json - 如何使用数据类在 Kotlin 中解决“无法编写 JSON:无限递归 (StackOverflowError)”?
问题描述
我知道该主题中有几篇文章,但我只是找不到使用 Kotlin 数据类的文章。所以我正在尝试使用 Spring Boot 在 Kotlin 中使用 H2 数据库制作一个 REST API,并且我也在使用 Postman。我的类的一些属性具有 List 类型。每次我尝试在 Postman 中为这些列表添加一些值然后尝试获取结果时,我都会收到以下错误:
我有三个班级:
食谱.kt:
@Entity
data class Recipe(
@Id
@SequenceGenerator(name = RECIPE_SEQUENCE, sequenceName = RECIPE_SEQUENCE, initialValue = 1, allocationSize = 1)
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0,
val name: String,
var cookTime: String?,
var servings: String?,
var directions: String?,
@OneToMany(cascade = [CascadeType.ALL], mappedBy = "recipe")
@JsonManagedReference
var ingredient: List<Ingredient>?,
@ManyToMany
@JsonManagedReference
@JoinTable(
name = "recipe_category",
joinColumns = [JoinColumn(name = "recipe_id")],
inverseJoinColumns = [JoinColumn(name = "category_id")]
)
var category: List<Category>?,
@Enumerated(value = EnumType.STRING)
var difficulty: Difficulty?
) { companion object { const val RECIPE_SEQUENCE: String = "RECIPE_SEQUENCE" } }
类别.kt
@Entity
data class Category(
@Id
@SequenceGenerator(name = CATEGORY_SEQUENCE, sequenceName = CATEGORY_SEQUENCE, initialValue = 1, allocationSize = 1)
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = 0,
var name: String,
@ManyToMany(mappedBy = "category")
@JsonBackReference
var recipe: List<Recipe>?
) { companion object { const val CATEGORY_SEQUENCE: String = "CATEGORY_SEQUENCE" } }
成分.kt
@Entity
data class Ingredient(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = 0,
var description: String?,
var amount: BigDecimal?,
@ManyToOne
@JsonBackReference
var recipe: Recipe?,
var unitOfMeasure: String?
)
食谱响应.kt
data class RecipeResponse (var id:Long,
var name:String,
var cookTime:String?,
var servings:String?,
var directions:String?,
var ingredient:List<Ingredient>?,
var category: List<Category>?,
var difficulty: Difficulty?)
食谱资源.kt
@RestController
@RequestMapping(value = [BASE_RECIPE_URL])
class RecipeResource(private val recipeManagementService: RecipeManagementService)
{
@GetMapping
fun findAll(): ResponseEntity<List<RecipeResponse>> = ResponseEntity.ok(this.recipeManagementService.findAll())
食谱管理服务.kt
@Service
class RecipeManagementService (@Autowired private val recipeRepository: RecipeRepository,
private val addRecipeRequestTransformer: AddRecipeRequestTransformer) {
fun findAll(): List<RecipeResponse> = this.recipeRepository.findAll().map(Recipe::toRecipeResponse)
解决方案
您必须在@ManyToOne 和 @OneToMany 字段之上添加@JsonIgnore 。Spring 将忽略返回该对象的那些字段。外汇。
@Entity
data class Ingredient(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = 0,
var description: String?,
var amount: BigDecimal?,
@ManyToOne
@JsonIgnore
var recipe: Recipe?, // This field will not be returned in JSON response.
var unitOfMeasure: String?
)
在这里,还要注意是否要在响应中包含此 ManyToOne 或 OneToMany 关系的某些字段。您必须使用 ObjectNode 制定您的响应,然后将其返回。
编辑 :
ObjectMapper objectMapper = new ObjectMapper();
@RestController
public ResponseEntity<String> someFunction() throws Exception {
ObjectNode msg = objectMapper.createObjectNode();
msg.put("success", true);
msg.put("field1", object.getValue1());
msg.put("field2", object.getValue2());
return ResponseEntity.ok()
.header("Content-Type", "application/json")
.body(objectMapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(res));
}
这里的代码是java,你可以把它转换成Kotlin,我认为它会是一样的。在这里,您可以编写自己的对象名称 ex,而不是 object。成分.getDescription() 并且可以生成响应。
推荐阅读
- excel - 为每个循环嵌套(Excel VBA)
- python - 我们可以创建一个具有相邻列的矩阵吗?
- rest - REST API:在单个查询中创建嵌套资源
- typescript - Loopback4 - 绑定时的身份验证 JWT 服务错误
- javascript - 如何使用复选框添加 IF 块
- python - Spotify API 从名称中查找艺术家 ID?
- c++ - 永无止境的文件读取循环(C++)
- r - 用希腊(即 LaTeX)符号替换图例标签/文本
- python - Pandas 以特殊字符分隔的分组和求和数据列
- javascript - Google App Script 中是否有不同的 Javascript 对象?