Setting JSON deserialisation features in Java SDK 3+

Using Spring Couchbase

I’m struggling to find a way to specifiy deserialisation feature, FAIL_ON_UNKNOWN_PROPERTIES to FALSE

    var result = getBucket().defaultCollection().get(id);
    return result.contentAs(clazz);

This code throws an error if the couchbase document contains elements not present in the class.

The Spring ObjectMapper is configured to allow this, so I tried to override the cluster environment configuration to use the Spring object mapper, but all documents come back from the database as blank content.

@Override
protected void configureEnvironment(Builder builder) {
// this mapper is the spring managed mapper
var s = JacksonJsonSerializer.create(mapper);
builder.jsonSerializer(s);
super.configureEnvironment(builder);
}

Hi Simon,

all documents come back from the database as blank content.

That’s surprising. If your deserialization depends on Jackson annotations, are you using the annotations from the com.faster.xml package? The ones repackaged under the com.couchbase namespace won’t work with Spring’s ObjectMapper.

If that’s not the problem, can you try a little experiment where you manually grab the JSON content and try to deserialize it using the Spring ObjectMapper?

Thanks,
David

Hi David

Thanks for the response. Yeah there’s nothing wrong with the JSON data.

    @Autowired ObjectMapper mapper;
    
    public <T> T get(String id, Class<T> clazz) {
        var result = getBucket().defaultCollection().get(id);
        var data = result.contentAsObject();
        try {
            return mapper.readValue(data.toString(), clazz);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } 
    }

This was my original kludge. I’m now using

@JsonIgnoreProperties(ignoreUnknown = true)

on the POJO which is obviously a neater solution =)

While it would be nice to know I’m using the same Mapper in couchbase SDK as Spring code, it’s not the end of the world

Just to prove it, this code runs fine when I use the configuration override with Spring ObjectMapper

    public <T> T get(String id, Class<T> clazz) {
        var result = getBucket().defaultCollection().get(id);
        
        var test = result.contentAsObject();
        assert(test.toString().equals("{}"));

        assert(result.contentAsObject() != null);
        return result.contentAs(clazz);
    }

So the issue is that the getContentAsObject is broken by using Spring ObjectMapper

I’m using Spring Boot 2.3.4 with the spring-boot-starter-data-couchbase

Which seems to pull in couchbase java client 3.0.8

So the issue is that the getContentAsObject is broken by using Spring ObjectMapper

I forgot something important. For contentAsObject() to work, it’s necessary to register the Couchbase JsonValueModule with the Spring ObjectMapper. This is mentioned in the Javadoc but it’s easy to overlook.

(This discussion has got us thinking about ways to remove that requirement…)

Too well hidden for me =)

So that works great. Many thanks. It might be smart of Spring Couchbase Starter to register the bean below I guess.

In case Google brings someone here, this is one way to configure Couchbase SDK to use the the Spring managed ObjectMapper.

@Configuration("config-couchbase")
public class CouchBaseAPIConfig extends AbstractCouchbaseConfiguration {
    @Autowired ObjectMapper mapper;
    
    // Spring will automatically add any bean of type databind.Module to it's default mapper
    // by adding Couchbase Module to Spring Mapper we can use same Mapper
   // in our code and Couchbase API
    @Bean
    public Module couchbaseJsonValueModule() {
        return new JsonValueModule();
    }
    
    @Override
    protected void configureEnvironment(ClusterEnvironment.Builder builder) {
        // Tell couchbase API to use our Spring ObjectMapper. 
       //  One Mapper to rule JSONs and in our classes bind them
        var s = JacksonJsonSerializer.create(mapper);
        builder.jsonSerializer(s);
        super.configureEnvironment(builder);
    }
2 Likes

@SimonMottram - Thanks for your input. I’ve opened add couchbaseJsonValueModel bean to AbstractCouchbaseConfiguration · Issue #1130 · spring-projects/spring-data-couchbase · GitHub