Exception in thread "main" com.couchbase.client.core.error.DecodingFailureException: Deserialization of content into target class com.couchbase.client.java.json.JsonObject failed; encoded = "Employee1"
at com.couchbase.client.java.codec.DefaultJsonSerializer.deserialize(DefaultJsonSerializer.java:90)
at com.couchbase.client.java.kv.LookupInResult.contentAs(LookupInResult.java:105)
at com.couchbase.client.java.kv.LookupInResult.contentAsObject(LookupInResult.java:146)
at couchbaseRelatedpoc.sample.CouchbaseConnectivityTester.main(CouchbaseConnectivityTester.java:115)
Caused by: java.io.IOException: Expected START_OBJECT but got VALUE_STRING
at com.couchbase.client.java.json.RepackagedJsonValueModule.expectCurrentToken(RepackagedJsonValueModule.java:137)
at com.couchbase.client.java.json.RepackagedJsonValueModule.access$000(RepackagedJsonValueModule.java:33)
at com.couchbase.client.java.json.RepackagedJsonValueModule$AbstractJsonValueDeserializer.decodeObject(RepackagedJsonValueModule.java:67)
at com.couchbase.client.java.json.RepackagedJsonValueModule$JsonObjectDeserializer.deserialize(RepackagedJsonValueModule.java:131)
at com.couchbase.client.java.json.RepackagedJsonValueModule$JsonObjectDeserializer.deserialize(RepackagedJsonValueModule.java:128)
at com.couchbase.client.core.deps.com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4524)
at com.couchbase.client.core.deps.com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3527)
at com.couchbase.client.java.codec.DefaultJsonSerializer.deserialize(DefaultJsonSerializer.java:87)
... 3 more
Can someone tell me what I am doing wrong or how should this be done?
The value of the “name” field is a string. It’s not possible to get the content as a JsonObject, because it’s not a JSON Object
There are a couple of ways you could fix this. If you know the value is a string, read it like this:
String value = lookupResult.contentAs(0, String.class);
If you don’t know the type in advance, you can parse it as a Jackson JsonNode. This class can represent any kind of JSON value:
JsonNode value = lookupResult.contentAs(0, JsonNode.class);
It looks like you’re using the version of Jackson that’s repackaged inside the Couchbase SDK, so the class to import would be com.couchbase.client.core.deps.com.fasterxml.jackson.databind.JsonNode
Another option, if you don’t know the type in advance, would be to write:
Object value = lookupResult.contentAs(0, Object.class);
That would return the value as a String, List, Map, boxed primitive, or null.
I have a pojo Employee with four fields (String name, int age, String email ,int phone)
The Actual document in couchbase contains around 20 fields. But I need to select only the above four fields mentioned in pojo.
Approach 1:
I cannot use a kv api like get , because it will return the entire object. Approach 2
I could have written the below query to apply projection.
select name,age,email,phone from emp_bucket use keys “sample”
But it involves the query service and data service, since I know the document key , I am planning to use sub document API which will involve only the data service. Approach 3
Use subdocument API lookupIn to get the fields and build the pojo using reflection. code
public static void main(String args) {
Cluster cluster = Cluster.connect(host, userName, password);
Bucket bucket = cluster.bucket(bucketName);
Collection empCollection = bucket.defaultCollection();
String documentId = “sample123”;
Employee employee = new Employee();
List<LookupInSpec> specs = new ArrayList<>();
for (Field field : employee.getClass().getDeclaredFields()) {
specs.add(LookupInSpec.get(field.getName()));
}
LookupInResult lookupResult = empCollection.lookupIn(documentId, specs);
for (int i = 0; i < 4; i++) {
JsonNode value = lookupResult.contentAs(i, JsonNode.class);
System.out.println("value : " + value);
}
}
Result:
value : “Employee1”
value : 20
value : “user@demo.com”
value : 9823625211
This code is giving me the result I need, but the problem is when mapping the entity, if I can use the path attribute present in SubDocumentField . I can use it to map to the entity.
Is there a way to do this?
or is there a better approach to do this ?