简短的版本是:如何jsonb
使用 Spring Data Rest PATCH 方法修补 Postgres 字段中包含的 JSON 对象?
长版来了,请考虑以下实体:
@Entity
@Table(name = "examples")
public class Example {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String jsonobject;
@JsonRawValue
public String getJsonobject() {
return jsonobject == null ? null : jsonobject;
}
public void setJsonobject(JsonNode jsonobject) {
this.jsonobject = jsonobject == null ? null : jsonobject.toString();
}
}
jsonobject
属于 Postgres 类型jsonb
。这些 getter/setter 是这里提到的 Spring Data Rest 的序列化/反序列化方法。如这些答案中所述,我们还尝试为该字段提供自己的类型。
我们的目标是使用 Spring Data Rest 修补此字段包含的 JSON 对象。
例如:
GET /examples/1
{
"id": 1,
"jsonobject": {
"foo": {"bar": "Hello"},
"baz": 2
}
}
PATCH /examples/1
{
"jsonobject": {
"foo": {"bar": "Welcome"}
}
}
预期输出:
GET /examples/1
{
"id": 1,
"jsonobject": {
"foo": {"bar": "Welcome"},
"baz": 2
}
}
电流输出:
GET /examples/1
{
"id": 1,
"jsonobject": {
"foo": {"bar": "Welcome"}
}
}
Spring Data Rest 修补 Example 资源并覆盖每个请求属性的值,而不是尝试挖掘 JSON 对象的属性以仅修补请求的嵌套属性。
这是我们认为 Spring Data Rest 支持application/merge-patch+json
和application/json-patch+json
媒体类型会派上用场的时候。以下是每种媒体类型的输出:
application/merge-patch+json
:
PATCH /examples/1
{
"jsonobject": {
"foo": {"bar": "Welcome"}
}
}
输出:
GET /examples/1
{
"id": 1,
"jsonobject": {
"foo": {"bar": "Welcome"}
}
}
application/json-patch+json
:
PATCH /examples/1
[
{ "op": "replace", "path": "/jsonobject/foo/bar", "value": "Welcome" }
]
输出:
{
"cause": {
"cause": null,
"message": "EL1008E:(pos 8): Property or field 'foo' cannot be found on object of type 'java.lang.String' - maybe not public?"
},
"message": "Could not read an object of type class com.example.Example from the request!; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 8): Property or field 'foo' cannot be found on object of type 'java.lang.String' - maybe not public?"
}
这归结为相同的想法:仅查找实体属性,并且完全覆盖或未找到。
问题如下:有没有办法让 Spring Data Rest 理解它正在处理一个jsonb
字段,因此寻找 JSON 嵌套属性而不是只查找实体属性?
注意:@Embeddable/@Embedded
最有可能避免使用注释,因为它们意味着知道嵌套的属性名称,这会降低对jsonb
字段的兴趣。
感谢您的阅读。