private <T> T convertByteInDataForObject(ByteString data, Class<T> toType) {
byte[] bsonBytes = data.toByteArray();
ByteBuffer byteBuffer = ByteBuffer.wrap(bsonBytes);
ByteBufferBsonInput bsonInput = new ByteBufferBsonInput(new ByteBufNIO(byteBuffer));
BsonBinaryReader reader = new BsonBinaryReader(bsonInput);
BsonDocumentCodec codec = new BsonDocumentCodec();
BsonDocument bsonDocument = codec.decode(reader, DecoderContext.builder().build());
CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build()));
return pojoCodecRegistry.get(toType).decode(new BsonDocumentReader(bsonDocument), DecoderContext.builder().build());
}
I have a ByteString and a Class, the ByteString contains the bytes of a Mongo Document. Ultimately I have to convert the bytes to the given Java class object but you can't directly deserialize the bytes to a POJO if they were not serialized using Java.
So I am converting the bytes to BsonDocument first and then finally converting it to the Java class The decode function on the last line throws below exception
An exception occurred when decoding using the AutomaticPojoCodec.
Decoding into a 'CustomObject' failed with the following exception:
Failed to decode 'CustomObject'. Decoding 'name' errored with: readStartDocument can only be called when CurrentBSONType is DOCUMENT, not when CurrentBSONType is STRING.
A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type.
The document looks like this,
{
"_id" : "6776734a086ac4106c0ca431",
"custom_enum_field" : "custom_enum_1",
"private_float_field" : 1.001,
"private_int_field" : NumberLong(7),
"int_field" : NumberLong(1),
"string_field" : "text 4",
"enum_field" : "ENUM2",
"custom_object" : {
"name" : "blah",
"value" : "text",
"id" : NumberInt(182761),
"price" : 199.99,
"discount" : 10.2,
"quantity" : NumberLong(12882763230),
"list" : null,
"customSubObjectList" : [
{
"name" : "blah",
"value" : "text",
"id" : NumberInt(182761),
"price" : 199.99,
"discount" : 10.2,
"quantity" : NumberInt(1288276323)
}
],
"dob" : NumberLong(1735816009154)
},
"bit_field" : true
}
The java class:
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CustomObject {
private String name;
private String value;
private Integer id;
private Float price;
private Double discount;
private Long quantity;
private List<String> list;
private List<CustomSubObject> customSubObjectList;
private Date dob;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class CustomSubObject {
private String name;
private String value;
private Integer id;
private Float price;
private Double discount;
private Long quantity;
}
private <T> T convertByteInDataForObject(ByteString data, Class<T> toType) {
byte[] bsonBytes = data.toByteArray();
ByteBuffer byteBuffer = ByteBuffer.wrap(bsonBytes);
ByteBufferBsonInput bsonInput = new ByteBufferBsonInput(new ByteBufNIO(byteBuffer));
BsonBinaryReader reader = new BsonBinaryReader(bsonInput);
BsonDocumentCodec codec = new BsonDocumentCodec();
BsonDocument bsonDocument = codec.decode(reader, DecoderContext.builder().build());
CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build()));
return pojoCodecRegistry.get(toType).decode(new BsonDocumentReader(bsonDocument), DecoderContext.builder().build());
}
I have a ByteString and a Class, the ByteString contains the bytes of a Mongo Document. Ultimately I have to convert the bytes to the given Java class object but you can't directly deserialize the bytes to a POJO if they were not serialized using Java.
So I am converting the bytes to BsonDocument first and then finally converting it to the Java class The decode function on the last line throws below exception
An exception occurred when decoding using the AutomaticPojoCodec.
Decoding into a 'CustomObject' failed with the following exception:
Failed to decode 'CustomObject'. Decoding 'name' errored with: readStartDocument can only be called when CurrentBSONType is DOCUMENT, not when CurrentBSONType is STRING.
A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type.
The document looks like this,
{
"_id" : "6776734a086ac4106c0ca431",
"custom_enum_field" : "custom_enum_1",
"private_float_field" : 1.001,
"private_int_field" : NumberLong(7),
"int_field" : NumberLong(1),
"string_field" : "text 4",
"enum_field" : "ENUM2",
"custom_object" : {
"name" : "blah",
"value" : "text",
"id" : NumberInt(182761),
"price" : 199.99,
"discount" : 10.2,
"quantity" : NumberLong(12882763230),
"list" : null,
"customSubObjectList" : [
{
"name" : "blah",
"value" : "text",
"id" : NumberInt(182761),
"price" : 199.99,
"discount" : 10.2,
"quantity" : NumberInt(1288276323)
}
],
"dob" : NumberLong(1735816009154)
},
"bit_field" : true
}
The java class:
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CustomObject {
private String name;
private String value;
private Integer id;
private Float price;
private Double discount;
private Long quantity;
private List<String> list;
private List<CustomSubObject> customSubObjectList;
private Date dob;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class CustomSubObject {
private String name;
private String value;
private Integer id;
private Float price;
private Double discount;
private Long quantity;
}
Fixed it by first converting it to a json string and then converting it to POJO. It's not the most optimal way to do it so any further optimisations are welcomed.
private <T> T convertByteInDataForObject(ByteString data, Class<T> toType) {
try {
byte[] bsonBytes = data.toByteArray();
ByteBuffer byteBuffer = ByteBuffer.wrap(bsonBytes);
ByteBufferBsonInput bsonInput = new ByteBufferBsonInput(new ByteBufNIO(byteBuffer));
BsonBinaryReader reader = new BsonBinaryReader(bsonInput);
BsonDocumentCodec codec = new BsonDocumentCodec();
BsonDocument bsonDocument = codec.decode(reader, DecoderContext.builder().build());
return objectMapper.readValue(bsonDocument.toJson(), toType);
} catch (Exception e) {
throw new RuntimeException("Unable to parse to Object", e);
}
}