#1 2015-02-21 17:33:21

Dmitro25
Member
Registered: 2015-02-21
Posts: 19

How to add variable of type "Single" to JSON?

Hi.
I use "Single" float numbers in my application.
But when I try to add their values to JSON object I get double (or extended) precision in the result JSON. So JSON has excess data.
e.g.

var
  s: Single;
  v1: Variant;
begin
  s := 2.6666666;
  v1 := _Obj(['label', s]);
  caption := VariantSaveJSON(v1);
end;

As a result caption will contain "2.666666650772095"

So I have found a strange thing: when I try to add "Single" or "Double" variable to array:

  v1 := _Arr([]);
  v1.Add(s);

I get an error TTextWriter.AddVariantJSON(VType=16388). There is no error when only if I use "Extended" type.

PS: I use Delphi7

Offline

#2 2015-02-21 18:57:37

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,658
Website

Re: How to add variable of type "Single" to JSON?

For the first problem, I guess that TTextWriter.AddVariantJSON() uses TTextWriter.Add(doublevalue) so will convert the single into double...

In Delphi 7, AFAIK, TVarRec (i.e. array of const parameter, as used in _Arr[]) only support extended.

Could you create a ticket so that "single" type may be better handled?

Note that our ORM and our SOA features expect double or currency values, and have very limited support with single.
If you need exact precision, just use currency.

Offline

#3 2015-02-22 03:51:25

Dmitro25
Member
Registered: 2015-02-21
Posts: 19

Re: How to add variable of type "Single" to JSON?

I can give an example of task when I want to use "single" precision. I am writing an application to handle geodata. End-point devices use GPS-receivers to determine their location. Then they send data to server using GSM channel. My application requests data from the server and shows objects on a map.
GPS receivers send their data using NMEA format. This format uses only 8-9 significant digits to represent latitude and longitude. So "single" type was chosen for storing coordinates.
Client application communicate with the server using JSON format. And I see that when server sends coordinates It uses significantly more digits than necessary. I the future when number of end-point devices grows JSON message will have large extra length and lead to excessive internet traffic.
I looked at the source "SynCommons.pas" and found that the code provides for the possibility to use a "Single" (for example, declared and used constant "SINGLE_PRECISION"), but did not understand how to use this feature. I have tried several ways but got the same result.

Offline

#4 2015-02-22 08:00:50

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,658
Website

Re: How to add variable of type "Single" to JSON?

Offline

#5 2015-02-22 10:53:04

Dmitro25
Member
Registered: 2015-02-21
Posts: 19

Re: How to add variable of type "Single" to JSON?

Think you very much. The new version do exact what I want with variables of "Single" type.

Sorry for molestation. But I think you would resolve the error, about which I wrote above. It still alive. The following code:

var
  s: Double;
  v1: Variant;
begin
  v1 := _Arr([]);
  s := 1.23456;
  v1.Add(s);
  caption := VariantSaveJSON(v1);
end;

cause an error "TTextWriter.AddVariantJSON(VType=16389)" when variable "s" has type "Single" or "Double". Only declaration "s: Extended" cause no error. I think this is a serious error. Few people use the type "Single". But the type "Double" is very popular (I think it is more popular than "Extended" as for the reason of compatibility with "double" from "C" language and for the reason that its length is a multiple of 8 bytes, which is beneficial to program performance.

Offline

#6 2015-02-22 13:23:34

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,658
Website

Re: How to add variable of type "Single" to JSON?

Please see http://synopse.info/fossil/info/f69855c654
and http://synopse.info/fossil/info/846978294b

The issue when setting data with late-binding method (like v1.Add in your case) should be solved.

Double is also more popular because it is SSE2 compatible, whereas "extended" is a x87 type only.
For instance, the Delphi Win64 compiler does not support extended natively any more.
Note also that ARM has no support of extended, so every floating point should be "double", AFAIK.

Offline

#7 2015-02-22 14:12:19

Dmitro25
Member
Registered: 2015-02-21
Posts: 19

Re: How to add variable of type "Single" to JSON?

I tried the latest version of "SynCommons.pas" from http://synopse.info/fossil/info/846978294b
The behaviour with "Single" and "Double" types is improved.
Unfortunately, with new version of "SynCommons.pas" the following code starts to cause error "Invalid pointer operation":

var
  v1, obj: Variant;
begin
  v1 := _Arr([]);
  obj := _Obj(['id', 1]);
  v1.Add(obj);
  caption := VariantSaveJSON(v1);
end;

Also after error FastMM4 reports that memory leak appears.
Previous versions of "SynCommons.pas" have no problems with such code.

Offline

#8 2015-02-22 15:30:35

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,658
Website

Re: How to add variable of type "Single" to JSON?

Indeed.

Should be fixed by http://synopse.info/fossil/info/a525dcccc8

Offline

#9 2015-02-22 16:06:57

Dmitro25
Member
Registered: 2015-02-21
Posts: 19

Re: How to add variable of type "Single" to JSON?

Your newest version works fine both with "Single" type and with adding objects to array. Thank you.

Offline

#10 2015-02-22 19:08:13

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,658
Website

Re: How to add variable of type "Single" to JSON?

Note that you are using "late binding" to manage your TDocVariant storage.

In practice, using a local TDocVariantData, and directly its AddItem() / AddValue() methods then trans-typing it into a variant is both faster and safer than using v1.Add().
Ensure you read the doc about this.

Offline

Board footer

Powered by FluxBB