How to Ignore some fields during deserialization using MongoDB Java Driver?

Hi,

I’m dealing with below POJO for automatic serialization and deserialization using Mongo Java Driver:

@Builder
@Data
public class CaseDocument {
    @BsonId
    private long caseId;
    private String customerId; //Nullable
    private String addressId; //Nullable

    @BsonCreator
    public CaseDocument(...) {
        // Constructor
    }
}

Insert works fine. Retrieving the document by primary key and deserialization it into CaseDocument POJO works fine. Now I’m working on a query where I want to use projection to limit the number of fields returned but it throws an error. Below is how my query looks like:

FindIterable<CaseDocument> documents = mongoCollection.find(request.getQuery());
documents.projection(Projections.include("caseId", "customerId")); //Not including addressId
return documents.into(new ArrayList<>());

This gives me below error:
“org.bson.codecs.configuration.CodecConfigurationException: Could not construct new instance of: CaseDocument. Missing the following properties: [addressId]”

I can’t use @BsonIgnore on addressId because I want it to be persisted in the DB and retrieved for another query.

I saw there is BsonIgnoreExtraElements for C# for nothing similar for Java driver.

Hence my question is how can I achieve the desired result where Mongo Java Driver constructs the CaseDocument object without addressId field set?

I’m using 3.12 version of Mongo Java Driver.

Hello @Shubham_Gupta, welcome to the community.

Here is an appraoch.

You can get the result of the projection as List<Document> (of org.bson.Document) and use a mapper to map the fields from the Document to the CaseDocument POJO as shown below.

The mapper method can be like this:

// Maps an input Document to a CaseDocument and returns it.
static CaseDocument mapToCaseDocument(Document doc) {
	CaseDocument caseDoc = new CaseDocument();
	caseDoc.setCaseId(caseDoc.getLong("caseId"));
	caseDoc.setCustomerId(caseDoc.getString("customerId"));
	// Map other fields as needed (with any conversions, validations, etc.).
	// Throw a runtime exception in case could not be mapped correctly.
	return caseDoc;
}

So your modified code:

MongoCollection<Document> collection = db.getCollection("caseCollection");

List<CaseDocument> result = collection.find(request.getQuery())
		                              .projection(Projections.include("caseId", "customerId"))
		                              .into(new ArrayList<Document>())
		                              .stream()
		                              .map(doc -> mapToCaseDocument(doc))
		                              .collect(Collectors.toList());

Note, the code uses Java driver v3.12 and MongoDB v4.2.

Thanks for replying Prasad. I understand that there are other ways to achieve it but I was looking for an out of the box solution but looks like that support is not there.

I myself achieved it by handling the serialization and deserialization using Jackson (Created a class DocumentUtils with two functions to convert Document to CaseDocument and vice versa).

A custom mapper though looks good here but it becomes hard to handle when there are 10+ fields in the POJO. Also the JSON returned by org.bson.Document contains bson identifiers like $numberLong which again requires extra handling.

I’ll raise an issue for it on Jira.