Skip to content

[Patch available] FPJSON writes strange float output

Summary

The fpjson library always writes float values in scientific notation, e.g. 0.5 is written as 5.0000000000000000E-001. This is less readable for a human user and takes more space if saved to a file.

System Information

  • Operating system: Arch Linux (Should be OS independent)
  • Processor architecture: x86-64 (Should be architecture independent)
  • Compiler version: FPC 3.3.1 x86_64-linux-gtk2
  • Device: Computer

Steps to reproduce

program test;

uses fpjson;

begin
  with TJSONObject.Create(['value', 0.5]) do
  begin
    WriteLn(AsJSON);
    WriteLn(FormatJSON);
    Free;
  end;
end.

What is the current bug behavior?

{ "value" : 5.0000000000000000E-001 }
{
  "value" : 5.0000000000000000E-001
}

What is the expected (correct) behavior?

{ "value" : 0.5 }
{
  "value" : 0.5
}

Possible fixes

See attached patch file. The proposed fix uses the FloatToStr() function instead of the Str() function. The FloatToStr() function automatically uses the most compact output (either decimal notation or scientific notation).

2141a2142,2163
> const
>   // ensure thousandseparator and decimalseparator comply with JSON specification
>   JSONFormatSettings: TFormatSettings = (
>     CurrencyFormat: 1;
>     NegCurrFormat: 5;
>     ThousandSeparator: ',';
>     DecimalSeparator: '.';
>     CurrencyDecimals: 2;
>     DateSeparator: '-';
>     TimeSeparator: ':';
>     ListSeparator: ',';
>     CurrencyString: '$';
>     ShortDateFormat: 'd/m/y';
>     LongDateFormat: 'dd" "mmmm" "yyyy';
>     TimeAMString: 'AM';
>     TimePMString: 'PM';
>     ShortTimeFormat: 'hh:nn';
>     LongTimeFormat: 'hh:nn:ss';
>     ShortMonthNames: ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
>     LongMonthNames: ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'); ShortDayNames: ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); LongDayNames: ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
>     TwoDigitYearCenturyWindow: 50
>   );
2143,2146c2165
<   Str(FValue,Result);
<   // Str produces a ' ' in front where the - can go.
<   if (Result<>'') and (Result[1]=' ') then
<     Delete(Result,1,1);
---
>   Result := FloatToStr(FValue, JSONFormatSettings);
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information