digitalmars.D.learn - Casting JSONValues arrays to native arrays ... ??? ...
- james.p.leblanc (52/52) Sep 23 2021 Dear D-ers,
- Steven Schveighoffer (33/75) Sep 23 2021 Note that this creates a JSONValue array which *copies* the values of
- james.p.leblanc (14/28) Sep 23 2021 Steve,
- james.p.leblanc (20/25) Sep 23 2021 Here comes a minor update (small rearrangement in mapping/array
- james.p.leblanc (17/29) Sep 23 2021 Sigh ... my suggested "minor edit" above produces a "map result"
- Steven Schveighoffer (14/43) Sep 24 2021 At first I thought that was allocating 2 arrays, but I didn't realize
Dear D-ers, In attempting to cast JSONValues that hold arrays to "native" array types, I have hit some issues. Example code: ```d import std.stdio; import std.json; void main(){ JSONValue jj; jj["d"] = [ 1.234 ]; // a "dummy" double value jj["ba"] = [ true, false, true]; // "ba" boolean array writeln("typeid(jj): ", typeid(jj), ", jj: ", jj ); // various things that I thought might work, but do NOT writeln("typeid(z4): ", typeid(z4), ", z4: ", z4 ); } ``` Attempts 1,2, and 3 yield compilation errors (which I somewhat understand): question.d(12): Error: cannot cast expression `jj.opIndex("ba")` of type `JSONValue` to `bool` question.d(13): Error: cannot cast expression `jj.opIndex("ba")` of type `JSONValue` to `bool[]` question.d(14): Error: cannot cast expression `jj.opIndex("ba").array()` of type `JSONValue[]` to `bool` However, if I comment out the offending attempts (1, 2, and 3), then it compiles, and can run ... but produces a result which I very much do NOT understand: typeid(jj): std.json.JSONValue, jj: {"ba":[true,false,true],"d":[1.23399999999999999]} typeid(z4): bool[], z4: [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false] Hmmmm... is there a standard way to push these JSONValues into nice native array types? (The real code is eventually going to be using traits and mixins ... but I do not think this should pose additional problems). All help and illumination thankfully received. Best Regards, James
Sep 23 2021
On 9/23/21 2:20 PM, james.p.leblanc wrote:Dear D-ers, In attempting to cast JSONValues that hold arrays to "native" array types, I have hit some issues. Example code: ```d import std.stdio; import std.json; void main(){ JSONValue jj; jj["d"] = [ 1.234 ]; // a "dummy" double value jj["ba"] = [ true, false, true]; // "ba" boolean arrayNote that this creates a JSONValue array which *copies* the values of the boolean array, converting them to JSONValue (which is what a JSONValue array stores).writeln("typeid(jj): ", typeid(jj), ", jj: ", jj ); // various things that I thought might work, but do NOTA JSONValue cannot be cast to a boolean (it does not provide the appropriate opCast)These try to cast something that is not an array to an array or vice versa. These are not supported unless the type itself has an `opCast` overload.Casting one array type to another is like pointing at the array that represents the original type *as if* it were of the new type. No translation is made, you are pointing at the same memory! The length is adjusted based on the size of the original array element and the size of the new one. For instance: ```d int[] arr = [1]; auto a2 = cast(ubyte[])arr; assert(a2.length == 4); assert(a2 == cast(ubyte[])([1, 0, 0, 0])); // assuming little endian ```However, if I comment out the offending attempts (1, 2, and 3), then it compiles, and can run ... but produces a result which I very much do NOT understand: typeid(jj): std.json.JSONValue, jj: {"ba":[true,false,true],"d":[1.23399999999999999]} typeid(z4): bool[], z4: [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false]This is an array of JSONValue, with each byte interpreted as if it were a bool.Hmmmm... is there a standard way to push these JSONValues into nice native array types? (The real code is eventually going to be using traits and mixins ... but I do not think this should pose additional problems).How you really do this: ```d import std.algorithm : map; auto z5 = jj["ba"] // get the JSONValue that is at the key "ba" .map!(v => v.get!bool) // map each value into a boolean .array // create an array out of the results; assert z5 == [true, false, true]; ``` (warning, untested) -Steve
Sep 23 2021
On Thursday, 23 September 2021 at 19:04:47 UTC, Steven Schveighoffer wrote:On 9/23/21 2:20 PM, james.p.leblanc wrote:Dear D-ers, In attempting to cast JSONValues that hold arrays to "native"How you really do this: ```d import std.algorithm : map; auto z5 = jj["ba"] // get the JSONValue that is at the key "ba" .map!(v => v.get!bool) // map each value into a boolean .array // create an array out of the results; assert z5 == [true, false, true]; ``` (warning, untested) -SteveSteve, Your thorough explanations have helped me understand quite much. Thank you for your energy and patience in these forum contributions. In fact, I had begun to think that "map", may be what was needed here and I had made a few naive attempts ... but this did not go so well. With your suggested solution, I believe I can make headway on this. Thanks Again, James
Sep 23 2021
On Thursday, 23 September 2021 at 19:18:11 UTC, james.p.leblanc wrote:On Thursday, 23 September 2021 at 19:04:47 UTC, Steven Schveighoffer wrote:Here comes a minor update (small rearrangement in mapping/array ordering) for anyone who may be interested. With this small edit to the suggested code, it works just fine! Here: ```d auto z5 = jj["ba"].array.map!(v => v.get!bool); writeln("typeid(z5): ", typeid(z5), ", z5: ", z5); writeln("z5: ", z5); ``` Produces: typeid(jj): std.json.JSONValue, jj: {"ba":[true,false,true],"d":[1.23399999999999999]} typeid(z5): question.main.MapResult!(__lambda2, JSONValue[]).MapResult, z5: [true, false, true] z5: [true, false, true] Cheers, JamesOn 9/23/21 2:20 PM, james.p.leblanc wrote:Dear D-ers,
Sep 23 2021
On Thursday, 23 September 2021 at 20:32:36 UTC, james.p.leblanc wrote:On Thursday, 23 September 2021 at 19:18:11 UTC, james.p.leblanc wrote:Sigh ... my suggested "minor edit" above produces a "map result" instead of the desired native array ... here is the **fix** by appending ".array" at the end (which is the suffix Steve originally offered). The following gives the desired **bool[]** result. ```d import std.array; auto z5 = jj["ba"].array.map!(v => v.get!bool).array; writeln("typeid(z5): ", typeid(z5), ", z5: ", z5); writeln("z5: ", z5); ``` Regards, JamesOn Thursday, 23 September 2021 at 19:04:47 UTC, Steven Schveighoffer wrote:``` Produces: typeid(jj): std.json.JSONValue, jj: {"ba":[true,false,true],"d":[1.23399999999999999]} typeid(z5): question.main.MapResult!(__lambda2, JSONValue[]).MapResult, z5: [true, false, true] z5: [true, false, true]On 9/23/21 2:20 PM, james.p.leblanc wrote:
Sep 23 2021
On 9/24/21 12:58 AM, james.p.leblanc wrote:On Thursday, 23 September 2021 at 20:32:36 UTC, james.p.leblanc wrote:At first I thought that was allocating 2 arrays, but I didn't realize `JSONValue.array` was an actual member! When I saw your original code, I assumed the `.array` call was a call to `std.array.array`, and that `JSONValue` was somehow usable as a range. So yes, that's what I should have written. I admit I have not used `JSONValue`. That `array` accessor is quite a poor name due to the vast prevalence of using `std.array.array` to make an array out of some range. When using vibe.d's JSON type, I usually do `jsval[]` to access the array portion. Note, you may want to consider whether you actually need a concrete array, as using the map result is pretty much equivalent, yet doesn't allocate anything. -STeveOn Thursday, 23 September 2021 at 19:18:11 UTC, james.p.leblanc wrote:Sigh ... my suggested "minor edit" above produces a "map result" instead of the desired native array ... here is the **fix** by appending ".array" at the end (which is the suffix Steve originally offered). The following gives the desired **bool[]** result. ```d import std.array; auto z5 = jj["ba"].array.map!(v => v.get!bool).array; writeln("typeid(z5): ", typeid(z5), ", z5: ", z5); writeln("z5: ", z5); ```On Thursday, 23 September 2021 at 19:04:47 UTC, Steven Schveighoffer wrote:``` Produces: typeid(jj): std.json.JSONValue, jj: {"ba":[true,false,true],"d":[1.23399999999999999]} typeid(z5): question.main.MapResult!(__lambda2, JSONValue[]).MapResult, z5: [true, false, true] z5: [true, false, true]On 9/23/21 2:20 PM, james.p.leblanc wrote:
Sep 24 2021