www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - std.json cannot read an array floats back from file

reply Yuri <hello yuri.online> writes:
Hi there,

consider the following simple use case:

   import std.json;
   float[] floats = [1,2,3];
   JSONValue j = "{}".parseJSON;
   j.object["floats"] = floats;
   std.file.write("test.json", j.toString);
   JSONValue jj = readText("test.json").parseJSON;
   jj.object["floats"].array[1].floating.writeln;

It is expected to print '2' in the console, however an exception 
is thrown:

std.json.JSONException /build/ldc-I3nwWj/ldc-0.17.1/runtime/pho
os/std/json.d(235): JSONValue is not a floating type

while the below works fine:

   import std.json;
   float[] floats = [1,2,3];
   JSONValue j = "{}".parseJSON;
   j.object["floats"] = floats;
   j.object["floats"].array[1].floating.writeln;

any pointers to what could be going wrong?
Jul 02
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 2 July 2017 at 21:07:40 UTC, Yuri wrote:
 It is expected to print '2' in the console, however an 
 exception is thrown:

 std.json.JSONException /build/ldc-I3nwWj/ldc-0.17.1/runtime/pho
os/std/json.d(235): JSONValue is not a floating type
I think it just read the json string of "1" as being an integer instead of a float, so the reader thought it was integral instead of floating. It should prolly just transparently auto-convert, but it doesn't seem to. Try accessing the int instead and see waht happens.
Jul 02
parent reply Yuri <hello yuri.online> writes:
On Sunday, 2 July 2017 at 21:12:48 UTC, Adam D. Ruppe wrote:
 On Sunday, 2 July 2017 at 21:07:40 UTC, Yuri wrote:
 It is expected to print '2' in the console, however an 
 exception is thrown:

 std.json.JSONException /build/ldc-I3nwWj/ldc-0.17.1/runtime/pho
os/std/json.d(235): JSONValue is not a floating type
I think it just read the json string of "1" as being an integer instead of a float, so the reader thought it was integral instead of floating. It should prolly just transparently auto-convert, but it doesn't seem to. Try accessing the int instead and see waht happens.
Yes, when accessing .integer instead of .floating then it works, unfortunately that is not suitable for the task at hand, it has to be a float.
Jul 03
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 3 July 2017 at 13:26:52 UTC, Yuri wrote:
 Yes, when accessing .integer instead of .floating then it 
 works, unfortunately that is not suitable for the task at hand, 
 it has to be a float.
Just write a helper function that casts it yourself: double numeric(JSONValue v) { if(v.type == JSON_VALUE.FLOAT) return v.floating; else if(v.type == JSON_VALUE.INTEGER) return v.integer; else if(v.type == JSON_VALUE.UINTEGER) // I think it has this too return v.uinteger; throw new Exception("not a numeric type, instead: " ~ to!string(v.type)); } and then you should be able to do jj.object["floats"].array[1].numeric.writeln; and have it return float regardless of if it is 1 or 1.0
Jul 03
parent Yuri <yuri-d disclosure.ie> writes:
On Monday, 3 July 2017 at 13:34:50 UTC, Adam D. Ruppe wrote:
 On Monday, 3 July 2017 at 13:26:52 UTC, Yuri wrote:
 Yes, when accessing .integer instead of .floating then it 
 works, unfortunately that is not suitable for the task at 
 hand, it has to be a float.
Just write a helper function that casts it yourself: double numeric(JSONValue v) { if(v.type == JSON_VALUE.FLOAT) return v.floating; else if(v.type == JSON_VALUE.INTEGER) return v.integer; else if(v.type == JSON_VALUE.UINTEGER) // I think it has this too return v.uinteger; throw new Exception("not a numeric type, instead: " ~ to!string(v.type)); } and then you should be able to do jj.object["floats"].array[1].numeric.writeln; and have it return float regardless of if it is 1 or 1.0
Thanks Adam, that will work for me. I wish though there was no need for jumping these hoops in a standard language lib but I guess it would be a topic for another discussion.
Jul 03
prev sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
Yuri wrote:

 Hi there,

 consider the following simple use case:

    import std.json;
    float[] floats = [1,2,3];
    JSONValue j = "{}".parseJSON;
    j.object["floats"] = floats;
    std.file.write("test.json", j.toString);
    JSONValue jj = readText("test.json").parseJSON;
    jj.object["floats"].array[1].floating.writeln;

 It is expected to print '2' in the console, however an exception is 
 thrown:

 std.json.JSONException /build/ldc-I3nwWj/ldc-0.17.1/runtime/pho
os/std/json.d(235): 
 JSONValue is not a floating type

 while the below works fine:

    import std.json;
    float[] floats = [1,2,3];
    JSONValue j = "{}".parseJSON;
    j.object["floats"] = floats;
    j.object["floats"].array[1].floating.writeln;

 any pointers to what could be going wrong?
'cause what you got back is `JSON_TYPE.INTEGER`. dunno why it is there at all, as JSON has no "integers" per se, but it read as integer, and `.floating` failed type checking. so, write your own wrapper that will convert INTEGER/UINTEGER/FLOAT to `double`. i think this is the best solution (if there can be "best solution" with std.json at all).
Jul 02
parent reply Yuri <hello yuri.online> writes:
On Sunday, 2 July 2017 at 21:15:41 UTC, ketmar wrote:
 so, write your own wrapper that will convert 
 INTEGER/UINTEGER/FLOAT to `double`. i think this is the best 
 solution (if there can be "best solution" with std.json at all).
I share your sentiment in relation to std.json, ketmar. On a side note, what would be a better way to serialize/deserialize objects in D if std.json does not cut it? It does not have to be JSON serialization although would be preferred.
Jul 03
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
Yuri wrote:

 On Sunday, 2 July 2017 at 21:15:41 UTC, ketmar wrote:
 so, write your own wrapper that will convert INTEGER/UINTEGER/FLOAT to 
 `double`. i think this is the best solution (if there can be "best 
 solution" with std.json at all).
I share your sentiment in relation to std.json, ketmar. On a side note, what would be a better way to serialize/deserialize objects in D if std.json does not cut it? It does not have to be JSON serialization although would be preferred.
it depends of the types of your objects. simple json-like (de)serializer for objects with fixed layout can be done in very small amount of code[0]. that's what i am using (and it can *read* json into structs too, i'm actually using it to parse some jsons -- idgames API replies, for example). [0] http://repo.or.cz/iv.d.git/blob_plain/HEAD:/txtser.d
Jul 03
parent reply Yuri <yuri-d disclosure.ie> writes:
On Monday, 3 July 2017 at 14:04:47 UTC, ketmar wrote:
 Yuri wrote:

 On Sunday, 2 July 2017 at 21:15:41 UTC, ketmar wrote:
 [...]
I share your sentiment in relation to std.json, ketmar. On a side note, what would be a better way to serialize/deserialize objects in D if std.json does not cut it? It does not have to be JSON serialization although would be preferred.
it depends of the types of your objects. simple json-like (de)serializer for objects with fixed layout can be done in very small amount of code[0]. that's what i am using (and it can *read* json into structs too, i'm actually using it to parse some jsons -- idgames API replies, for example). [0] http://repo.or.cz/iv.d.git/blob_plain/HEAD:/txtser.d
Thanks, ketmar, I'll have a look into the code, the objects I am dealing with are not particularly complex, that might work well enough.
Jul 03
parent ketmar <ketmar ketmar.no-ip.org> writes:
Yuri wrote:

 On Monday, 3 July 2017 at 14:04:47 UTC, ketmar wrote:
 Yuri wrote:

 On Sunday, 2 July 2017 at 21:15:41 UTC, ketmar wrote:
 [...]
I share your sentiment in relation to std.json, ketmar. On a side note, what would be a better way to serialize/deserialize objects in D if std.json does not cut it? It does not have to be JSON serialization although would be preferred.
it depends of the types of your objects. simple json-like (de)serializer for objects with fixed layout can be done in very small amount of code[0]. that's what i am using (and it can *read* json into structs too, i'm actually using it to parse some jsons -- idgames API replies, for example). [0] http://repo.or.cz/iv.d.git/blob_plain/HEAD:/txtser.d
Thanks, ketmar, I'll have a look into the code, the objects I am dealing with are not particularly complex, that might work well enough.
it doesn't matter if objects are complex or not; the only thing that matters is that you must really have *objects* that can be described by structs, not "freeform" json. i.e. txtser cannot deserialize json into dom-like tree structure, only deserialize structs/arrays/aas. but structs can contain other structs, and AA values can be structs too, and so on. i.e.: if you don't need arbitrary access to arbitrary json fields, but only have to deserialize something with known layout, txtser probably can do the job for you.
Jul 03