After executing findbyId the object is not getting deserialized and its showing blank or null values for nested inner data objects.
Eg: content{
body{
parts{
.
.
body is showing as blank value when deserialized in spring boot 3.4.3 and reactive couchbase sdk which is using Jackson 2.18 internally to deserialize.
Data Schema is not defined as POJO since the contents can be dynamic and it was working fine with older version of spring and couchbase.
Can you show somethings that might help diagnose the issue? The repository interface, the entity, the document and the code that makes the call?
Data Schema is not defined as POJO
hmmm… Repositories need to know what object to create for deserialzation. If you have the repository entity defined to be a java.lang.Object, then spring-data-couchbase will happily create one for you. But a java.lang.Object has no fields.
My code is using repository.findById(contentId); which is a part of ReactiveCrudRepository class.
It returns object which does not deserialize nested inner objects, and it returns blank value of (body and stimulus tags) as shown below. Since Jackson’s new version has better entity type, it needs tight concrete pojo to create java objects.
What I want is to use same ReactiveCrudRepository’s findById but instead of using Jackson it should use GSON and should not bother about the entity type and just convert my object into json object irrespective of the enityt type definition (since we have dynamic content in couchbase) as shown below in the correct format with body and stimulus tags.
Below is the incorrect JSON format
{
“isLatest”: true,
“metaData”: {
“contentType”: “JSON”,
“contentSource”: “ACS”,
“useLatestContent”: true
},
“content”: {
“body”: {},
“schema”: “https://xwwwwx.com/cite/schema/xxxxx/1.0”,
“stimulus”: {},
“tdxContentDisplayed”: “TDX”,
“title”: “q2 (edited)”,
“type”: “assessmentItem”
},
“_id”: “fae45cxxxxxxxxxxxxxxxxxxxxxxxxx4206648ab5”,
“_ver”: “af4c0571-4cab-4ba7-895d-4f2001889d1b”,
“_docType”: “content”,
“_created”: “2025-05-13T15:23:10+00:00”
}
Below is the Correct JSON format from couchbase
{
“isLatest”: true,
“metaData”: {
“contentType”: “JSON”,
“contentSource”: “ACS”,
“useLatestContent”: true
},
“content”: {
“schema”: “https://xxesesex.com/cite/schema/xxxx/1.0”,
“tdxContentDisplayed”: “TDX”,
“body”: {
“parts”: [
{
“content”: [
{
“feedback”: [
{
“condition”: “choice_0”,
“content”: [
{
“type”: “text”,
“text”: “aaaaaaaaaaaaaaaaa”
}
]
},
{
“condition”: “choice_1”,
“content”: [
{
“type”: “text”,
“text”: “bbbbbbbbbbbbbbbbbbb”
}
]
}
],
“schema”: “https://xxesesx.com/cite/schema/xyz/1.0”,
“labelVAlign”: “top”,
“labelType”: “none”,
“maxChoices”: 1,
“columnCount”: 0,
“id”: “newMCQ”,
“choices”: [
{
“content”: [
{
“type”: “text”,
“text”: “a2”
}
],
“id”: “choice_0”
},
{
“content”: [
{
“type”: “text”,
“text”: “a2”
}
],
“id”: “choice_1”
}
],
“type”: “multipleChoiceInteraction”,
“prompt”: {
“content”: [
{
“type”: “text”,
“text”: “q2”
}
]
},
“choiceSelection”: false,
“validation”: {
“correctChoices”: [
“choice_0”
]
}
}
],
“id”: “part_0”
}
]
},
“title”: “q2 (edited)”,
“type”: “assessmentItem”,
“stimulus”: {
“content”: [
{
“type”: “text”,
“text”: “q2”
}
]
}
},
“_id”: “fae4xwwwwxxxxxxxxwwwwwwxxxxxxxxxx206648ab5”,
“_ver”: “af4xwwwxxxxxxxxxwwwwxxxxxxxx2001889d1b”,
“_docType”: “content”,
“_created”: “2025-05-13T15:23:10+00:00”
}
Please show the code for your definition of the repository interface, and the code that calls findById() and accesses the result, and perhaps I can figure out how to make it work.
it should use GSON and should not bother about the entity type and just convert my object into json object irrespective of the enityt type definition
The serialization/deserialization is done by the mappingCouchbaseConverter() defined in AbstractCouchbaseConverter. If you want different serialization/deserialization, then you can override that method in your implementation. But - since you don’t want any of the spring-data-couchbase serialization/deserialization - why not just use the Couchbase SDK directly? If you still want to use spring-data-couchbase templates and/or repositories, the Couchbase SDK is accessible via repository.getOperations().getCouchbaseClientFactory()… or template.getCouchbaseClientFactory()…
Hi
Thanks @mreiche
I found the solution by using customised findById but this will have lot of changes in all the places where-ever I made call to my findById method since I have customised it.
What I exactly need is something in findById which internally will use Gson rather than Jackson and deserialize my result objects obtained from couchbase.
Below function which was not able to deserialize my nested inner json objects
public Mono findUserContentById(String contentId) {
return repository.findById(contentId);
}
Below function which resolved my issue
default Mono findById(String id, Class clazz) {
return Mono.fromFuture(
getOperations().getCouchbaseClientFactory().getBucket().async().defaultCollection().get(id))
.retry(3).flatMap(result -> {
if (result == null || result.contentAs(JsonObject.class) == null) {
return Mono.empty();
}
JsonObject jsonObject = result.contentAs(JsonObject.class);
String rawJsonString = jsonObject.toString();
LOGGER.debug("Get findById response : {}", rawJsonString);
return Mono.just(MapperUtil.createObjectfromJson(rawJsonString, clazz));
}).onErrorResume(Mono::error);
}
Ok. But won’t all the methods in that repository need to be custom methods then?
Why not just use the java SDK directly with a transcoder that uses GSON ?