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 array

Note 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 NOT

    auto z1 = cast(bool)   jj["ba"];           // attempt #1

A JSONValue cannot be cast to a boolean (it does not provide the appropriate opCast)

    auto z2 = cast(bool[]) jj["ba"];           // attempt #2
    auto z3 = cast(bool)   jj["ba"].array;     // attempt #3

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.

    auto z4 = cast(bool[]) jj["ba"].array;     // attempt #4

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

Reply via email to