JSON3.jl icon indicating copy to clipboard operation
JSON3.jl copied to clipboard

higher rank arrays should appear as nested lists

Open ExpandingMan opened this issue 6 years ago • 4 comments

For example, see the behavior of JSON.jl

julia> A = [1 0
            0 1]
2×2 Array{Int64,2}:
 1  0
 0  1

julia> JSON.json(A)
"[[1,0],[0,1]]"

julia> A = rand(2,2,2)
2×2×2 Array{Float64,3}:
[:, :, 1] =
 0.293369   0.187349
 0.0572265  0.719968

[:, :, 2] =
 0.521351  0.454227
 0.546091  0.773648

julia> JSON.json(A)
"[[[0.2933693401153792,0.057226458190521745],[0.18734882624283,0.7199679429526]],[[0.52135120453497,0.54609145253139],[0.4542265690601863,0.7736478960773061]]]"

It would also be nice to at least have the option for there to be an inverse of this. That is, a function which reads in a nested JSON and automatically constructs an AbstractArray of the appropriate rank. For me personally, this would be a great default behavior in cases where all elements are a common type, but I can see how this would be controversial.

It might also be worth considering doing column-wise instead of row-wise ordering because that would match Julia's memory layout, however this might clash with conventions that exist outside of Julia.

ExpandingMan avatar Jun 25 '19 18:06 ExpandingMan

I agree with this proposal and serialization of multidimensional array is convenient for scientific computing if HDF5 is not suitable for the scenario. Instead of nested arrays, a flattened array for data and another array for shape can be used. For example, for a matrix

A = [1 2; 3 4]

We can write it as:

{
    "shape" : [2, 2],
    "data" : [1, 2, 3, 4]
}

shape parameter can be used to reshape the data to multidimensional array.

metab0t avatar Sep 14 '20 03:09 metab0t

I commented on a newer issue here, but by using Tables.matrix, Tables.table, and the JSONTables.jl package, it's actually pretty easy to convert a Matrix to json output as object of arrays or array of objects, and then read that back in as a matrix.

quinnj avatar Dec 10 '20 21:12 quinnj

Coming back to this; I think it'd be possible to special-case higher-rank Arrays when reading/writing. Writing would be a little easier, because I think there are ways to iterate over high-rank arrays so you get the nested slices. Reading might be trickier though, because we need to detect the rank initially.

That said, I think it might even be easier/less breaking to only support reading in the explicit case: i.e. when you do something like JSON3.read(json, Matrix{Float64}). Then we can just have a specialized read method for Matrix or other higher-rank Arrays that will expect the nested arrays to read from. Anybody feel like taking a stab at this?

quinnj avatar Apr 14 '21 04:04 quinnj

I actually prefer the idea of @metab0t to serialize the data in a linear index style and also store the shape. It seems like serializing arrays as nested lists would make it hard to distinguish them from nested vectors.

lassepe avatar Apr 30 '21 11:04 lassepe