diff --git a/jackson-modules/jackson-conversions-3/pom.xml b/jackson-modules/jackson-conversions-3/pom.xml
index ac4fbfcfb0a6..1790852e979b 100644
--- a/jackson-modules/jackson-conversions-3/pom.xml
+++ b/jackson-modules/jackson-conversions-3/pom.xml
@@ -42,6 +42,27 @@
json
${json.version}
+
+ org.mongojack
+ mongojack
+ ${mongojack.version}
+
+
+ org.mongodb
+ mongodb-driver-sync
+ ${mongodb-driver.version}
+
+
+ de.undercouch
+ bson4jackson
+ ${bson4jackson.version}
+
+
+ de.flapdoodle.embed
+ de.flapdoodle.embed.mongo
+ ${flapdoodle.version}
+ test
+
@@ -57,6 +78,10 @@
5.13.2
20240303
+ 5.0.3
+ 5.6.1
+ 2.18.0
+ 4.21.0
\ No newline at end of file
diff --git a/jackson-modules/jackson-conversions-3/src/main/java/com/baeldung/jackson/pojomapping/BsonProductMapper.java b/jackson-modules/jackson-conversions-3/src/main/java/com/baeldung/jackson/pojomapping/BsonProductMapper.java
new file mode 100644
index 000000000000..a2befff9fd66
--- /dev/null
+++ b/jackson-modules/jackson-conversions-3/src/main/java/com/baeldung/jackson/pojomapping/BsonProductMapper.java
@@ -0,0 +1,48 @@
+package com.baeldung.jackson.pojomapping;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.undercouch.bson4jackson.BsonFactory;
+import org.bson.BsonBinaryWriter;
+import org.bson.BsonDocument;
+import org.bson.Document;
+import org.bson.RawBsonDocument;
+import org.bson.codecs.BsonDocumentCodec;
+import org.bson.codecs.EncoderContext;
+import org.bson.io.BasicOutputBuffer;
+
+import java.io.IOException;
+
+public class BsonProductMapper {
+
+ private final ObjectMapper objectMapper;
+
+ public BsonProductMapper() {
+ this.objectMapper = new ObjectMapper(new BsonFactory());
+ }
+
+ public byte[] toBytes(Product product) throws JsonProcessingException {
+ return objectMapper.writeValueAsBytes(product);
+ }
+
+ public Product fromBytes(byte[] bson) throws IOException {
+ return objectMapper.readValue(bson, Product.class);
+ }
+
+ public Document toDocument(Product product) throws IOException {
+ byte[] bytes = toBytes(product);
+ RawBsonDocument bsonDoc = new RawBsonDocument(bytes);
+ return Document.parse(bsonDoc.toJson());
+ }
+
+ public Product fromDocument(Document document) throws IOException {
+ BsonDocument bsonDoc = document.toBsonDocument();
+ BasicOutputBuffer buffer = new BasicOutputBuffer();
+ new BsonDocumentCodec().encode(
+ new BsonBinaryWriter(buffer),
+ bsonDoc,
+ EncoderContext.builder().build()
+ );
+ return fromBytes(buffer.toByteArray());
+ }
+}
diff --git a/jackson-modules/jackson-conversions-3/src/main/java/com/baeldung/jackson/pojomapping/Product.java b/jackson-modules/jackson-conversions-3/src/main/java/com/baeldung/jackson/pojomapping/Product.java
new file mode 100644
index 000000000000..d06bb33f3875
--- /dev/null
+++ b/jackson-modules/jackson-conversions-3/src/main/java/com/baeldung/jackson/pojomapping/Product.java
@@ -0,0 +1,45 @@
+package com.baeldung.jackson.pojomapping;
+
+import org.mongojack.Id;
+import org.mongojack.ObjectId;
+
+public class Product {
+
+ @ObjectId
+ @Id
+ private String id;
+ private String name;
+ private double price;
+
+ public Product() {
+ }
+
+ public Product(String name, double price) {
+ this.name = name;
+ this.price = price;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public double getPrice() {
+ return price;
+ }
+
+ public void setPrice(double price) {
+ this.price = price;
+ }
+}
diff --git a/jackson-modules/jackson-conversions-3/src/main/java/com/baeldung/jackson/pojomapping/ProductService.java b/jackson-modules/jackson-conversions-3/src/main/java/com/baeldung/jackson/pojomapping/ProductService.java
new file mode 100644
index 000000000000..c132f9bdad9f
--- /dev/null
+++ b/jackson-modules/jackson-conversions-3/src/main/java/com/baeldung/jackson/pojomapping/ProductService.java
@@ -0,0 +1,27 @@
+package com.baeldung.jackson.pojomapping;
+
+import com.mongodb.client.MongoDatabase;
+import org.bson.UuidRepresentation;
+import org.mongojack.JacksonMongoCollection;
+
+public class ProductService {
+
+ private final JacksonMongoCollection collection;
+
+ public ProductService(MongoDatabase database) {
+ this.collection = JacksonMongoCollection.builder()
+ .build(database, "products", Product.class, UuidRepresentation.STANDARD);
+ }
+
+ public void save(Product product) {
+ collection.insertOne(product);
+ }
+
+ public Product findById(String id) {
+ return collection.findOneById(id);
+ }
+
+ public long count() {
+ return collection.countDocuments();
+ }
+}
diff --git a/jackson-modules/jackson-conversions-3/src/test/java/com/baeldung/jackson/pojomapping/BsonProductMapperUnitTest.java b/jackson-modules/jackson-conversions-3/src/test/java/com/baeldung/jackson/pojomapping/BsonProductMapperUnitTest.java
new file mode 100644
index 000000000000..b6c9774abe07
--- /dev/null
+++ b/jackson-modules/jackson-conversions-3/src/test/java/com/baeldung/jackson/pojomapping/BsonProductMapperUnitTest.java
@@ -0,0 +1,82 @@
+package com.baeldung.jackson.pojomapping;
+
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class BsonProductMapperUnitTest {
+
+ private BsonProductMapper mapper;
+ private Product product;
+
+ @BeforeEach
+ void setUp() {
+ mapper = new BsonProductMapper();
+ product = new Product("Test Product", 29.99);
+ }
+
+ @Test
+ void whenSerializingProduct_thenReturnsByteArray() throws IOException {
+ byte[] bytes = mapper.toBytes(product);
+
+ assertNotNull(bytes);
+ assertTrue(bytes.length > 0);
+ }
+
+ @Test
+ void givenSerializedProduct_whenDeserializing_thenReturnsProduct() throws IOException {
+ byte[] bytes = mapper.toBytes(product);
+
+ Product deserializedProduct = mapper.fromBytes(bytes);
+
+ assertEquals(product.getName(), deserializedProduct.getName());
+ assertEquals(product.getPrice(), deserializedProduct.getPrice(), 0.01);
+ }
+
+ @Test
+ void whenConvertingProductToDocument_thenReturnsValidDocument() throws IOException {
+ Document document = mapper.toDocument(product);
+
+ assertNotNull(document);
+ assertEquals(product.getName(), document.getString("name"));
+ assertEquals(product.getPrice(), document.getDouble("price"), 0.01);
+ }
+
+ @Test
+ void whenRoundTrippingProduct_thenDataIsPreserved() throws IOException {
+ Document document = mapper.toDocument(product);
+ Product roundTrippedProduct = mapper.fromDocument(document);
+
+ assertEquals(product.getName(), roundTrippedProduct.getName());
+ assertEquals(product.getPrice(), roundTrippedProduct.getPrice(), 0.01);
+ }
+
+ @Test
+ void givenDocument_whenConvertingToProduct_thenReturnsProduct() throws IOException {
+ Document document = new Document()
+ .append("name", "Document Product")
+ .append("price", 49.99);
+
+ Product convertedProduct = mapper.fromDocument(document);
+
+ assertEquals("Document Product", convertedProduct.getName());
+ assertEquals(49.99, convertedProduct.getPrice(), 0.01);
+ }
+
+ @Test
+ void givenProductWithNullFields_whenSerializing_thenHandlesGracefully() throws IOException {
+
+ Product productWithNulls = new Product();
+ productWithNulls.setPrice(10.0);
+
+ byte[] bytes = mapper.toBytes(productWithNulls);
+ Product deserializedProduct = mapper.fromBytes(bytes);
+
+ assertNull(deserializedProduct.getName());
+ assertEquals(10.0, deserializedProduct.getPrice(), 0.01);
+ }
+}
diff --git a/jackson-modules/jackson-conversions-3/src/test/java/com/baeldung/jackson/pojomapping/ProductServiceLiveTest.java b/jackson-modules/jackson-conversions-3/src/test/java/com/baeldung/jackson/pojomapping/ProductServiceLiveTest.java
new file mode 100644
index 000000000000..c478e7caf8fc
--- /dev/null
+++ b/jackson-modules/jackson-conversions-3/src/test/java/com/baeldung/jackson/pojomapping/ProductServiceLiveTest.java
@@ -0,0 +1,62 @@
+package com.baeldung.jackson.pojomapping;
+
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoClients;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.mongo.transitions.Mongod;
+import de.flapdoodle.embed.mongo.transitions.RunningMongodProcess;
+import de.flapdoodle.reverse.TransitionWalker;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class ProductServiceLiveTest {
+
+ private TransitionWalker.ReachedState mongodbProcess;
+ private MongoClient mongoClient;
+ private ProductService productService;
+
+ @BeforeEach
+ void setUp() {
+ mongodbProcess = Mongod.instance().start(Version.Main.V5_0);
+ var serverAddress = mongodbProcess.current().getServerAddress();
+
+ mongoClient = MongoClients.create(String.format("mongodb://%s:%d",
+ serverAddress.getHost(), serverAddress.getPort()));
+ productService = new ProductService(mongoClient.getDatabase("testdb"));
+ }
+
+ @AfterEach
+ void tearDown() {
+ if (mongoClient != null) {
+ mongoClient.close();
+ }
+ if (mongodbProcess != null) {
+ mongodbProcess.close();
+ }
+ }
+
+ @Test
+ void whenSavingProduct_thenProductIsPersisted() {
+ Product product = new Product("Laptop", 999.99);
+
+ productService.save(product);
+
+ assertNotNull(product.getId());
+ assertEquals(1, productService.count());
+ }
+
+ @Test
+ void whenSavingProductWithAllFields_thenAllFieldsArePersisted() {
+ Product product = new Product("Full Product", 199.99);
+
+ productService.save(product);
+ Product foundProduct = productService.findById(product.getId());
+
+ assertNotNull(foundProduct.getId());
+ assertEquals("Full Product", foundProduct.getName());
+ assertEquals(199.99, foundProduct.getPrice(), 0.01);
+ }
+}