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