簡體   English   中英

Spring 數據 Rest - POST 請求返回狀態 400

[英]Spring Data Rest - POST request return status 400

更新 Spring 從版本 1.5 到 2.7 后,POST 請求返回狀態 400。

我有 Feed 存儲庫:

interface FeedRepository : PagingAndSortingRepository<Feed, Long> { 
// Custom methods 
}

Spring 數據 Rest 為他生成默認 controller,所以我可以在以下位置提出請求:localhost:8080/api/feeds

進給 class:

@Entity
@DiscriminatorValue("feed")
class Feed(
    id: Long, //Superclass Fields,

    @ManyToOne
    val parent: Feed?,

    @OneToMany(mappedBy = "parent", cascade = [CascadeType.REMOVE])
    val children: List<Feed>,

    @Column(name = "extension_id")
    var extensionId: String?,

    @Column(name = "create_date")
    var created: Date = Calendar.getInstance().time

) : Resource(id, //Superclass Fields)

資源 class:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
@JsonSubTypes(value = [
// SubTypes
JsonSubTypes.Type(value = Feed::class, name = "feed"),
])
abstract class Resource(

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    override val id: Long,

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "resource_tags",
            joinColumns = [JoinColumn(name = "resource_id")],
            inverseJoinColumns = [JoinColumn(name = "tag_id")]
    )
    val tags: Set<Tag> = Collections.emptySet(),

    @JsonIgnore
    @OneToMany(mappedBy = "resource", cascade = [CascadeType.REMOVE])
    val menuItems: List<Menu> = ArrayList(0),

    // Another Fields
)

對象映射器 Bean:

@Bean(name = arrayOf("OBJECT_MAPPER_BEAN"))
fun jsonObjectMapper(): ObjectMapper {
    return Jackson2ObjectMapperBuilder.json()
            .serializationInclusion(JsonInclude.Include.ALWAYS)
            .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .featuresToDisable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)
            .featuresToDisable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)
            .modules(JavaTimeModule())
            .build<ObjectMapper>()
}

如果我使用有效負載執行保存請求(POST localhost:8080/api/feeds):

{
  "type": "packages.Feed",
  "parent": "https://localhost:8080/api/feeds/251",
  "extensionId": null,
  "title": {
    "localizedStrings": [
        "https://localhost:8080/api/localizedStrings/4319"
    ]
  }
}

我得到狀態 400 和錯誤:

JSON 解析錯誤:JSON 屬性標簽的 [simple type, class Feed] 值的實例化失敗,因為缺少(因此為 NULL)類型的創建者參數標簽 nested exception is com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class Feed] value failed for JSON property tags due to missing (therefore NULL) value for creator parameter tags which is a non-nullable type\ n 在 [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); 行:10,列:1](通過引用鏈:Feed["tags"])

看起來 Jackson 庫處理請求正文的方式略有不同,因為這在更新之前有效。

我試圖為 Feed class @JsonProperty(required = false) 中的“標簽”字段指定注釋,但沒有幫助。

任何想法如何解決這一問題? 我將非常感謝您的幫助。

問題中缺少一些基本代碼,例如錯誤消息中提到的屬性tags如何獲取其值。 class Feed很可能會像這樣繼續

class Feed(
    id: Long,
    tags: Set<Tag>,

    [other code here]

) : Resource(id, tags, //Superclass Fields)

如果是這種情況,Jackson 將在構建 class Feed時遇到問題,因為缺少tags的默認值(即使它是在父級中定義的)。 在這種情況下,為 class Feed中的tags添加默認值應該可以解決此問題。

class Feed(
    id: Long,
    tags: Set<Tag> = Collections.emptySet(),

    [other code here]

我通過將配置添加到 Jackson Kotlin 模塊來解決此問題。

現在創建的 ObjectMapper 看起來像:

@Bean(name = arrayOf("OBJECT_MAPPER_BEAN"))
fun jsonObjectMapper(): ObjectMapper {
            return Jackson2ObjectMapperBuilder.json()
            .serializationInclusion(JsonInclude.Include.ALWAYS)
            .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .featuresToDisable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)
            .featuresToDisable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)
            .modules(JavaTimeModule(), KotlinModule.Builder()
                .configure(KotlinFeature.NullToEmptyCollection, true)
                .configure(KotlinFeature.NullToEmptyMap, true)
                .configure(KotlinFeature.NullIsSameAsDefault, true)
                .configure(KotlinFeature.SingletonSupport, false)
                .configure(KotlinFeature.StrictNullChecks, false)
                .build()
            )
            .build<ObjectMapper>()
}

在運行了幾個測試之后,我可以說一切都按預期工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM