Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for FixedSizeList in array_to_json_array #4361

Merged
merged 3 commits into from
Jun 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions arrow-array/src/array/fixed_size_list_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

use crate::array::print_long_array;
use crate::builder::{FixedSizeListBuilder, PrimitiveBuilder};
use crate::iterator::FixedSizeListIter;
use crate::{make_array, Array, ArrayAccessor, ArrayRef, ArrowPrimitiveType};
use arrow_buffer::buffer::NullBuffer;
use arrow_buffer::ArrowNativeType;
Expand Down Expand Up @@ -277,6 +278,11 @@ impl FixedSizeListArray {
}
builder.finish()
}

/// constructs a new iterator
pub fn iter(&self) -> FixedSizeListIter<'_> {
FixedSizeListIter::new(self)
}
}

impl From<ArrayData> for FixedSizeListArray {
Expand Down Expand Up @@ -389,14 +395,28 @@ impl std::fmt::Debug for FixedSizeListArray {
}
}

impl<'a> ArrayAccessor for &'a FixedSizeListArray {
type Item = ArrayRef;

fn value(&self, index: usize) -> Self::Item {
FixedSizeListArray::value(self, index)
}

unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
FixedSizeListArray::value(self, index)
}
}

#[cfg(test)]
mod tests {
use super::*;
use arrow_buffer::{bit_util, BooleanBuffer, Buffer};
use arrow_schema::Field;

use crate::cast::AsArray;
use crate::types::Int32Type;
use crate::Int32Array;
use arrow_buffer::{bit_util, BooleanBuffer, Buffer};
use arrow_schema::Field;

use super::*;

#[test]
fn test_fixed_size_list_array() {
Expand Down
9 changes: 9 additions & 0 deletions arrow-array/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,15 @@ pub fn as_list_array(arr: &dyn Array) -> &ListArray {
as_generic_list_array::<i32>(arr)
}

/// Force downcast of an [`Array`], such as an [`ArrayRef`] to
/// [`FixedSizeListArray`], panic'ing on failure.
#[inline]
pub fn as_fixed_size_list_array(arr: &dyn Array) -> &FixedSizeListArray {
arr.as_any()
.downcast_ref::<FixedSizeListArray>()
.expect("Unable to downcast to fixed size list array")
}

/// Force downcast of an [`Array`], such as an [`ArrayRef`] to
/// [`LargeListArray`], panic'ing on failure.
#[inline]
Expand Down
3 changes: 3 additions & 0 deletions arrow-array/src/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::array::{
ArrayAccessor, BooleanArray, FixedSizeBinaryArray, GenericBinaryArray,
GenericListArray, GenericStringArray, PrimitiveArray,
};
use crate::FixedSizeListArray;

/// An iterator that returns Some(T) or None, that can be used on any [`ArrayAccessor`]
///
Expand Down Expand Up @@ -124,6 +125,8 @@ pub type GenericStringIter<'a, T> = ArrayIter<&'a GenericStringArray<T>>;
pub type GenericBinaryIter<'a, T> = ArrayIter<&'a GenericBinaryArray<T>>;
/// an iterator that returns Some(T) or None, that can be used on any FixedSizeBinaryArray
pub type FixedSizeBinaryIter<'a> = ArrayIter<&'a FixedSizeBinaryArray>;
/// an iterator that returns Some(T) or None, that can be used on any FixedSizeListArray
pub type FixedSizeListIter<'a> = ArrayIter<&'a FixedSizeListArray>;
/// an iterator that returns Some(T) or None, that can be used on any ListArray
pub type GenericListArrayIter<'a, O> = ArrayIter<&'a GenericListArray<O>>;

Expand Down
36 changes: 34 additions & 2 deletions arrow-json/src/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,13 @@ pub fn array_to_json_array(array: &ArrayRef) -> Result<Vec<Value>, ArrowError> {
None => Ok(Value::Null),
})
.collect(),
DataType::FixedSizeList(_, _) => as_fixed_size_list_array(array)
.iter()
.map(|maybe_value| match maybe_value {
Some(v) => Ok(Value::Array(array_to_json_array(&v)?)),
None => Ok(Value::Null),
})
.collect(),
DataType::Struct(_) => {
let jsonmaps = struct_array_to_jsonmap_array(array.as_struct())?;
Ok(jsonmaps.into_iter().map(Value::Object).collect())
Expand Down Expand Up @@ -606,10 +613,12 @@ mod tests {
use std::io::{BufReader, Seek};
use std::sync::Arc;

use crate::reader::*;
use serde_json::json;

use arrow_buffer::{Buffer, ToByteSlice};
use arrow_data::ArrayData;
use serde_json::json;

use crate::reader::*;

use super::*;

Expand Down Expand Up @@ -1483,4 +1492,27 @@ mod tests {
assert_eq!(serde_json::from_str::<Value>(r).unwrap(), expected_json,);
}
}

#[test]
fn test_array_to_json_array_for_fixed_size_list_array() {
let expected_json = vec![
json!([0, 1, 2]),
json!(null),
json!([3, null, 5]),
json!([6, 7, 45]),
];

let data = vec![
Some(vec![Some(0), Some(1), Some(2)]),
None,
Some(vec![Some(3), None, Some(5)]),
Some(vec![Some(6), Some(7), Some(45)]),
];

let list_array =
FixedSizeListArray::from_iter_primitive::<Int32Type, _, _>(data, 3);
let list_array = Arc::new(list_array) as ArrayRef;

assert_eq!(array_to_json_array(&list_array).unwrap(), expected_json);
}
}