I am writing a general calls to store and retrieve data via JSON. So when loading the data from JSON I can verify that it is a TJSONNumber
but lack a proper way to find out if it is integer
or double
. Currently I do it this way, but I guess there are better ways?
FDataStore: TDictionary<string, Variant>;
for index := 0 to Value.Count - 1 do begin
Pair := Value.Pairs[Index];
if Pair.JsonValue is TJSONNumber then
try
FDataStore.AddOrSetValue(Pair.JsonString.Value, (Pair.JsonValue as TJSONNumber).AsInt);
except
FDataStore.AddOrSetValue(Pair.JsonString.Value, (Pair.JsonValue as TJSONNumber).AsDouble);
end;
end;
Unfortunately, TJSONNumber
doesn't tell you the actual type, so you have to parse the original text to figure it out yourself.
For instance, by using TryStrToInt64()
(rather than try..except
), eg:
var
IntValue: Int64;
V: Variant;
if TryStrToInt64(TJSONNumber(Pair.JsonValue).Value, IntValue) then
begin
if IntValue >= Min(Integer) and IntValue <= Max(Integer) then
V := Integer(IntValue)
else
V := IntValue;
end else
V := TJSONNumber(Pair.JsonValue).AsDouble);
FDataStore.AddOrSetValue(Pair.JsonString.Value, Value);
Alternatively, you could scan the JSON string for '.'
and 'E'
characters (the only non-digit characters allowed in a JSON number besides '+'
and '-'
), eg:
var
V: Variant;
if LastDelimiter('.Ee', TJSONNumber(Pair.JsonValue).Value) = 0 then
begin
var IntValue := TJSONNumber(Pair.JsonValue).AsInt64;
if IntValue >= Min(Integer) and IntValue <= Max(Integer) then
V := Integer(IntValue)
else
V := IntValue
end
else
V := TJSONNumber(Pair.JsonValue).AsDouble;
FDataStore.AddOrSetValue(Pair.JsonString.Value, V);
Note that TJSONNumber
is also convertible to UInt
and UInt64
, so you may want to consider handling those types, as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With