oatpp / oatpp-mongo

Oat++ native BSON + MongoDB driver implementation based on Oat++ object-mapping sub-framework.
https://oatpp.io/
Apache License 2.0
6 stars 3 forks source link

Object mapper gives error when deserializing Int64 #12

Open ns-wxin opened 1 year ago

ns-wxin commented 1 year ago

This problem is relatively easy to reproduce. When Object Mapper (default) is trying to decode a serialized string (JSON) of an object containing a field that is a list of Int64 and when one of the number's absolute value is small (-103 in this case). The object mapper would throw exception:

2023-07-08 00:06:29 ERROR localhost 494264 DLPFP 0: UploadController.cpp:00678 trid=342343234 rqid=0 tenantid=2400 user='' Decoding error for: { "simhash" : [ -1374461674807444439, -103, 1803150389721624332, -292347449805 ]}, err: [oatpp::mongo::bson::Utils::readPrimitive()]: Error. Can't deserialize Int64 value. BSON document value type is expected to be Int64.

Sample string: { "simhash" : [ -1374461674807444439, -103, 1803150389721624332, -292347449805 ]}"

The condition I found for this error is that the int64 absolute value is small. In the test code, it works for testString2 where I changed the small value to a big one. Looks like when the value is between [-2147483648, 2147483648) ie. 2^31, the deserializer will give this error.

Code snippets:

class TestDto : public oatpp::DTO {
    DTO_INIT(TestDto, DTO)

    DTO_FIELD(List<Int64>, simhash);
};

oatpp::Object<TestDto> decodeTestDto(const std::string &line)
{
    auto doc = bsoncxx::from_json(line);
    auto view = doc.view();
    auto bson = oatpp::String((const char *)view.data(), view.length());
    return m_objectMapper.readFromString<oatpp::Object<TestDto>>(bson);
}

Testing Code and sample string:

std::string testString = "{ \"simhash\" : [ -1374461674807444439, -103, 1803150389721624332, -292347449805 ]}";
// the following string works
// std::string testString2 = "{ \"simhash\" : [ -1374461674807444439, -103446167480744443, 1803150389721624332, -292347449805 ]}";
try {
    oatpp::Object<TestDto> testDto = m_allFpGenerator->decodeTestDto(testString);
    LOG(INFO) << "TestDto decode OK for " << testString;
} catch (const std::exception &exc) {
    LOG(ERROR) << "Decoding error for: " << testString << ", err: " << exc.what(); 
}
ns-wxin commented 1 year ago

@lganzzzo when you get a chance, could you take a look at the deserializer? Thanks.

ns-wxin commented 1 year ago

@lganzzzo or @BillyONeal , could you take a quick look at this issue? It's pretty straight-forward to reproduce it. Any number in [-2147483648, 2147483648) can't be deserialized to an Int64. Thanks.