JsonTools icon indicating copy to clipboard operation
JsonTools copied to clipboard

FloatToStr when decimal separator is not a dot

Open lainz opened this issue 5 years ago • 6 comments

Hi, for example when the system locale is Spanish we use comma as decimal separator "," instead of dot "." that causes a problem when using FloatToStr and StrToFloat.

lainz avatar Dec 12 '19 13:12 lainz

@lainz use DefaultFormatSettings.DecimalSeparator := ','

skrzacikus avatar Dec 12 '19 13:12 skrzacikus

That's not a solution. The solution must be in JsonTools. We already patched it, so it always uses dot instead of comma. But I'm reporting so others doesn't have the same issue.

Our patch is like this:

function StrToFloatDecDef(s: string; rDefault: real):Double;
var sTemp:string;
begin
   sTemp:=StringReplace(s,'.',DecimalSeparator,[rfReplaceAll]);
   result:=StrToFloatDef(sTemp, rDefault);
end;


function FloattoStrDec(aValor: Real): String;
var
  sTmp: string;
begin
    sTmp := FormatFloat('0.0000',aValor);
    sTmp := StringReplace(sTmp, ThousandSeparator, '', [rfReplaceAll, rfIgnoreCase]);
    Result := StringReplace(sTmp, DecimalSeparator, '.',[rfReplaceAll, rfIgnoreCase]);
end;  

procedure TJsonNode.SetAsNumber(Value: Double);
begin
  if FParent = nil then
    Error(SRootNodeKind);
  if FKind <> nkNumber then
  begin
    Clear;
    FKind := nkNumber;
  end;
  FValue := FloattoStrDec(Value);
end;   

function TJsonNode.Add(const Name: string; const N: Double): TJsonNode; overload;
begin
  Result := Add(nkNumber, Name, FloattoStrDec(N));
end;   

function TJsonNode.GetAsNumber: Double;
begin
  if FParent = nil then
    Error(SRootNodeKind);
  if FKind <> nkNumber then
  begin
    Clear;
    FKind := nkNumber;
    FValue := '0';
    Exit(0);
  end;
  Result := StrToFloatDecDef(FValue, 0);
end;  

lainz avatar Dec 12 '19 14:12 lainz

Using TFormatSettings would be the solution:

procedure TJsonDataHelper.SetFloat(const Path:string;const AValue:Extended);
var
  FormatSettings : TFormatSettings;
  JsonData       : TJsonData;
begin
  Lock;
  JsonData := PathToObject(Path,nkNumber);
  if Assigned(JsonData) then
  begin
    {$IFDEF DCC}
    FormatSettings := TFormatSettings.Create;
    {$ENDIF}
    FormatSettings.DecimalSeparator := '.';
    try
      JsonData.Value := FormatFloat('0.0'+StringOfChar('#',30),AValue,FormatSettings);
    except
      JsonData.AsNull;
    end;
  end;
  Unlock;
end;

hafedh-trimeche avatar Aug 04 '20 20:08 hafedh-trimeche

@lainz I have the same issue. I found I had to change the locale of the machine to have a . as a decimal place. Do you have a pas file with your path applied?

JacoFourie avatar Apr 01 '21 22:04 JacoFourie

OK I added it myself and all is working. Thanks for this.

JacoFourie avatar Apr 01 '21 23:04 JacoFourie

You're welcome. I don't share my unit since I think I modified a bit more, and it requires some of the project files, so I can't share.

lainz avatar Apr 02 '21 15:04 lainz