I've marked this issue as major because a lot of people are using JSON for mobile app communication, and I discovered this because an incorrect invoice was sent (fortunately only during testing).
In this code:
import std.json;
import std.stdio;
void main() {
JSONValue json;
json.type = JSON_TYPE.FLOAT;
json.floating = 30738.22;
writeln(toJSON(&json));
}
the resulting output is:
30738.2
The problem is that all float serialization just uses to!string() from std.conv;
std.json should serialize to the standard @ json.org.
Comment #1 by rjmcguire — 2016-04-06T13:42:13Z
Created attachment 1594
possible patch
this patch just makes sure we always output using %f. I'm guessing %g technically has the bug because surely it shouldn't just remove part of the number _by default_
Comment #2 by b2.temp — 2016-05-21T20:40:56Z
(In reply to Rory from comment #1)
> Created attachment 1594 [details]
> possible patch
>
> this patch just makes sure we always output using %f. I'm guessing %g
> technically has the bug because surely it shouldn't just remove part of the
> number _by default_
%f doesn't work. It breaks some unittest.
the correct format specifier would be "%.9g" (9 comes from the constant FLT_DECIMAL_DIG).
see https://github.com/dlang/phobos/pull/4343
Comment #3 by thomas.bockman — 2016-05-22T02:37:51Z
The correct format specifier is ACTUALLY "%.18g", assuming that you want full lossless conversion. This is because:
1) JSON_TYPE.FLOAT is a 64-bit double, not 32-bit float!
2) cast(int)ceil(log(pow(2.0L, F.mant_dig - 1)) / log(10.0L) + 1) decimal digits are needed to represent some floating-point values, such as (1 + F.epsilon).
See this DPaste: https://dpaste.dzfl.pl/1bd14e5c3f83#line-25
Comment #4 by github-bugzilla — 2016-06-01T05:31:16Z