Mercurial > octave
diff libinterp/corefcn/jsondecode.cc @ 29994:eb768fc5e6b7
jsondecode.cc: Handle array of arrays and arrays of structs correctly (bug #60688)
* libinterp/corefcn/jsondecode.cc (decode_object_array): Resize struct array
if it has no fields.
* libinterp/corefcn/jsondecode.cc (decode_array_of_arrays): Handle struct
arrays correctly.
* test/json/jsondecode_BIST.tst: New tests.
Many thanks to an anonymous contributor.
author | Kai T. Ohlhus <k.ohlhus@gmail.com> |
---|---|
date | Wed, 18 Aug 2021 14:56:07 +0900 |
parents | c7c69808356f |
children | 4628ae890642 |
line wrap: on
line diff
--- a/libinterp/corefcn/jsondecode.cc Wed Aug 18 00:25:50 2021 -0400 +++ b/libinterp/corefcn/jsondecode.cc Wed Aug 18 14:56:07 2021 +0900 @@ -239,13 +239,22 @@ if (same_field_names) { octave_map struct_array; - Cell value (dim_vector (struct_cell.numel (), 1)); - for (octave_idx_type i = 0; i < field_names.numel (); ++i) + dim_vector struct_array_dims = dim_vector (struct_cell.numel (), 1); + + if (field_names.numel ()) { - for (octave_idx_type k = 0; k < struct_cell.numel (); ++k) - value(k) = struct_cell(k).scalar_map_value ().getfield (field_names(i)); - struct_array.assign (field_names(i), value); + Cell value (struct_array_dims); + for (octave_idx_type i = 0; i < field_names.numel (); ++i) + { + for (octave_idx_type k = 0; k < struct_cell.numel (); ++k) + value(k) = struct_cell(k).scalar_map_value () + .getfield (field_names(i)); + struct_array.assign (field_names(i), value); + } } + else + struct_array.resize (struct_array_dims, true); + return struct_array; } else @@ -286,6 +295,9 @@ // Only arrays with sub-arrays of booleans and numericals will return NDArray bool is_bool = cell(0).is_bool_matrix (); + bool is_struct = cell(0).isstruct (); + string_vector field_names = is_struct ? cell(0).map_value ().fieldnames () + : string_vector (); dim_vector sub_array_dims = cell(0).dims (); octave_idx_type sub_array_ndims = cell(0).ndims (); octave_idx_type cell_numel = cell.numel (); @@ -302,6 +314,13 @@ // return cell array if (cell(i).is_bool_matrix () != is_bool) return cell; + // If not struct arrays only, return cell array + if (cell(i).isstruct () != is_struct) + return cell; + // If struct arrays have different fields, return cell array + if (is_struct && (field_names.std_list () + != cell(i).map_value ().fieldnames ().std_list ())) + return cell; } // Calculate the dims of the output array @@ -310,21 +329,55 @@ array_dims(0) = cell_numel; for (auto i = 1; i < sub_array_ndims + 1; i++) array_dims(i) = sub_array_dims(i-1); - NDArray array (array_dims); - // Populate the array with specific order to generate MATLAB-identical output - octave_idx_type sub_array_numel = array.numel () / cell_numel; - for (octave_idx_type k = 0; k < cell_numel; ++k) + if (is_struct) { - NDArray sub_array_value = cell(k).array_value (); - for (octave_idx_type i = 0; i < sub_array_numel; ++i) - array(k + i*cell_numel) = sub_array_value(i); - } + octave_map struct_array; + array_dims.chop_trailing_singletons (); + + if (field_names.numel ()) + { + Cell value (array_dims); + octave_idx_type sub_array_numel = sub_array_dims.numel (); - if (is_bool) - return boolNDArray (array); + for (octave_idx_type j = 0; j < field_names.numel (); ++j) + { + // Populate the array with specific order to generate + // MATLAB-identical output. + for (octave_idx_type k = 0; k < cell_numel; ++k) + { + Cell sub_array_value = cell(k).map_value () + .getfield (field_names(j)); + for (octave_idx_type i = 0; i < sub_array_numel; ++i) + value(k + i * cell_numel) = sub_array_value(i); + } + struct_array.assign (field_names(j), value); + } + } + else + struct_array.resize(array_dims, true); + + return struct_array; + } else - return array; + { + NDArray array (array_dims); + + // Populate the array with specific order to generate MATLAB-identical + // output. + octave_idx_type sub_array_numel = array.numel () / cell_numel; + for (octave_idx_type k = 0; k < cell_numel; ++k) + { + NDArray sub_array_value = cell(k).array_value (); + for (octave_idx_type i = 0; i < sub_array_numel; ++i) + array(k + i * cell_numel) = sub_array_value(i); + } + + if (is_bool) + return boolNDArray (array); + else + return array; + } } //! Decodes any type of JSON arrays. This function only serves as an interface