Краткая версия: Как исправить объект JSON, содержащийся в поле Postgres jsonb
, с помощью метода Spring Data Rest PATCH?
Вот длинная версия, пожалуйста, рассмотрите следующую сущность:
@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
. Эти геттеры/установщики являются способом сериализации/десериализации для Spring Data Rest, упомянутого здесь. Мы также попытались присвоить полю собственный тип, как указано в этих ответов. а>.
Наша цель — исправить объект JSON, содержащийся в этом поле, с помощью Spring Data Rest.
Например:
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, а не только искать атрибуты сущности?
Nb: скорее всего, следует избегать аннотаций @Embeddable/@Embedded
, поскольку они подразумевают знание имен вложенных свойств, что снижает интерес к полю jsonb
.
Спасибо за чтение.