Short version: how to fix the JSON object contained in the Postgres jsonb field using the Spring Data Rest PATCH method?
Here is the long version, please consider the following object:
@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 is of type Postgres jsonb . These getter / setter is a way to serialize / deserialize it for the Spring Data Rest mentioned here . We also tried to provide a field for our type, as mentioned in these answers .
Our goal is to fix the JSON object this field contains using Spring Data Rest.
For example:
GET /examples/1 { "id": 1, "jsonobject": { "foo": {"bar": "Hello"}, "baz": 2 } } PATCH /examples/1 { "jsonobject": { "foo": {"bar": "Welcome"} } }
Expected Result:
GET /examples/1 { "id": 1, "jsonobject": { "foo": {"bar": "Welcome"}, "baz": 2 } }
Current output:
GET /examples/1 { "id": 1, "jsonobject": { "foo": {"bar": "Welcome"} } }
Spring Data Rest fixes the Example resource and redefines the value for each requested attribute instead of trying to insert only the correction of the requested nested properties into the properties of the JSON object.
This is when we thought that media support application/merge-patch+json and application/json-patch+json would matter Spring. Here are the outputs for each media type:
application/merge-patch+json :
PATCH /examples/1 { "jsonobject": { "foo": {"bar": "Welcome"} } }
Output:
GET /examples/1 { "id": 1, "jsonobject": { "foo": {"bar": "Welcome"} } }
application/json-patch+json :
PATCH /examples/1 [ { "op": "replace", "path": "/jsonobject/foo/bar", "value": "Welcome" } ]
Output:
{ "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?" }
Which boils down to the same idea: only the attributes of the entity are scanned and either completely redefined or not found.
The question is this: is there a way for Spring Data Rest to understand that it is dealing with a jsonb field and therefore is looking for nested JSON properties, not just searching for entity attributes?
Nb: @Embeddable/@Embedded Annotations are likely to be eliminated, as they imply knowledge of the names of nested properties, which will reduce interest for the jsonb field.
Thanks for reading.