Skip to content

Commit 6a4cdaf

Browse files
committed
Use Python's repr() to emit float values
This fixes issue python-rapidjson#101: RJ's dtoa() seems to have a weird behavior with particular floating point values. See also Tencent/rapidjson#1237.
1 parent f53e987 commit 6a4cdaf

2 files changed

Lines changed: 26 additions & 2 deletions

File tree

rapidjson.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,8 +2276,25 @@ dumps_internal(
22762276
else
22772277
writer->RawValue("Infinity", 8, kNumberType);
22782278
}
2279-
else
2280-
writer->Double(d);
2279+
else {
2280+
// The RJ dtoa() produces "strange" results for particular values, see #101:
2281+
// use Python's repr() to emit a raw value instead of writer->Double(d)
2282+
2283+
PyObject *dr = PyObject_Repr(object);
2284+
2285+
if (dr == NULL)
2286+
return false;
2287+
2288+
Py_ssize_t l;
2289+
const char* rs = PyUnicode_AsUTF8AndSize(dr, &l);
2290+
if (rs == NULL) {
2291+
Py_DECREF(dr);
2292+
return false;
2293+
}
2294+
2295+
writer->RawValue(rs, l, kNumberType);
2296+
Py_DECREF(dr);
2297+
}
22812298
}
22822299
else if (PyUnicode_Check(object)) {
22832300
Py_ssize_t l;

tests/test_base_types.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ def test_base_values(value, dumps, loads):
3030
assert loaded == value and type(loaded) is type(value)
3131

3232

33+
@pytest.mark.unit
34+
def test_float(dumps):
35+
value = 0.1 + 0.2
36+
dumped = dumps(value)
37+
assert dumped == '0.30000000000000004'
38+
39+
3340
@pytest.mark.unit
3441
def test_tuple(dumps):
3542
obj = [1, 2, 'a', 1.2, {'foo': 'bar'},]

0 commit comments

Comments
 (0)