You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by tu...@apache.org on 2023/06/05 18:43:51 UTC
[arrow-rs] branch master updated: Have array_to_json_array support MapArray (#4364)
This is an automated email from the ASF dual-hosted git repository.
tustvold pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/master by this push:
new 7c406e446 Have array_to_json_array support MapArray (#4364)
7c406e446 is described below
commit 7c406e4465ced4b3a69ef8ba4d1dbb341ce8d0c7
Author: dadepo <da...@gmail.com>
AuthorDate: Mon Jun 5 22:43:45 2023 +0400
Have array_to_json_array support MapArray (#4364)
* Have array_to_json_array support MapArray
* Have the iterator for MapArray return StructArray
---
arrow-array/src/array/map_array.rs | 22 +++++++++++++-
arrow-array/src/iterator.rs | 4 ++-
arrow-json/src/writer.rs | 59 ++++++++++++++++++++++++++++++++++++++
3 files changed, 83 insertions(+), 2 deletions(-)
diff --git a/arrow-array/src/array/map_array.rs b/arrow-array/src/array/map_array.rs
index cf0978f05..c98bca950 100644
--- a/arrow-array/src/array/map_array.rs
+++ b/arrow-array/src/array/map_array.rs
@@ -16,7 +16,10 @@
// under the License.
use crate::array::{get_offsets, print_long_array};
-use crate::{make_array, Array, ArrayRef, ListArray, StringArray, StructArray};
+use crate::iterator::MapArrayIter;
+use crate::{
+ make_array, Array, ArrayAccessor, ArrayRef, ListArray, StringArray, StructArray,
+};
use arrow_buffer::{ArrowNativeType, Buffer, NullBuffer, OffsetBuffer, ToByteSlice};
use arrow_data::{ArrayData, ArrayDataBuilder};
use arrow_schema::{ArrowError, DataType, Field};
@@ -116,6 +119,11 @@ impl MapArray {
value_offsets: self.value_offsets.slice(offset, length),
}
}
+
+ /// constructs a new iterator
+ pub fn iter(&self) -> MapArrayIter<'_> {
+ MapArrayIter::new(self)
+ }
}
impl From<ArrayData> for MapArray {
@@ -284,6 +292,18 @@ impl Array for MapArray {
}
}
+impl<'a> ArrayAccessor for &'a MapArray {
+ type Item = StructArray;
+
+ fn value(&self, index: usize) -> Self::Item {
+ MapArray::value(self, index)
+ }
+
+ unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
+ MapArray::value(self, index)
+ }
+}
+
impl std::fmt::Debug for MapArray {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MapArray\n[\n")?;
diff --git a/arrow-array/src/iterator.rs b/arrow-array/src/iterator.rs
index fa76e09b2..86f5d9912 100644
--- a/arrow-array/src/iterator.rs
+++ b/arrow-array/src/iterator.rs
@@ -21,7 +21,7 @@ use crate::array::{
ArrayAccessor, BooleanArray, FixedSizeBinaryArray, GenericBinaryArray,
GenericListArray, GenericStringArray, PrimitiveArray,
};
-use crate::FixedSizeListArray;
+use crate::{FixedSizeListArray, MapArray};
/// An iterator that returns Some(T) or None, that can be used on any [`ArrayAccessor`]
///
@@ -129,6 +129,8 @@ pub type FixedSizeBinaryIter<'a> = ArrayIter<&'a FixedSizeBinaryArray>;
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>>;
+/// an iterator that returns Some(T) or None, that can be used on any MapArray
+pub type MapArrayIter<'a> = ArrayIter<&'a MapArray>;
#[cfg(test)]
mod tests {
diff --git a/arrow-json/src/writer.rs b/arrow-json/src/writer.rs
index d2365118a..6fed0f747 100644
--- a/arrow-json/src/writer.rs
+++ b/arrow-json/src/writer.rs
@@ -94,6 +94,7 @@
//! ```
use std::iter;
+use std::sync::Arc;
use std::{fmt::Debug, io::Write};
use serde_json::map::Map as JsonMap;
@@ -202,6 +203,15 @@ pub fn array_to_json_array(array: &ArrayRef) -> Result<Vec<Value>, ArrowError> {
let jsonmaps = struct_array_to_jsonmap_array(array.as_struct())?;
Ok(jsonmaps.into_iter().map(Value::Object).collect())
}
+ DataType::Map(_, _) => as_map_array(array)
+ .iter()
+ .map(|maybe_value| match maybe_value {
+ Some(v) => Ok(Value::Array(array_to_json_array(
+ &(Arc::new(v) as ArrayRef),
+ )?)),
+ None => Ok(Value::Null),
+ })
+ .collect(),
t => Err(ArrowError::JsonError(format!(
"data type {t:?} not supported"
))),
@@ -617,6 +627,7 @@ mod tests {
use std::io::{BufReader, Seek};
use std::sync::Arc;
+ use arrow_array::builder::{Int32Builder, MapBuilder, StringBuilder};
use serde_json::json;
use arrow_buffer::{Buffer, ToByteSlice};
@@ -1520,4 +1531,52 @@ mod tests {
assert_eq!(array_to_json_array(&list_array).unwrap(), expected_json);
}
+
+ #[test]
+ fn test_array_to_json_array_for_map_array() {
+ let expected_json = serde_json::from_value::<Vec<Value>>(json!([
+ [
+ {
+ "keys": "joe",
+ "values": 1
+ }
+ ],
+ [
+ {
+ "keys": "blogs",
+ "values": 2
+ },
+ {
+ "keys": "foo",
+ "values": 4
+ }
+ ],
+ [],
+ null
+ ]))
+ .unwrap();
+
+ let string_builder = StringBuilder::new();
+ let int_builder = Int32Builder::with_capacity(4);
+
+ let mut builder = MapBuilder::new(None, string_builder, int_builder);
+
+ builder.keys().append_value("joe");
+ builder.values().append_value(1);
+ builder.append(true).unwrap();
+
+ builder.keys().append_value("blogs");
+ builder.values().append_value(2);
+ builder.keys().append_value("foo");
+ builder.values().append_value(4);
+ builder.append(true).unwrap();
+ builder.append(true).unwrap();
+ builder.append(false).unwrap();
+
+ let array = builder.finish();
+
+ let map_array = Arc::new(array) as ArrayRef;
+
+ assert_eq!(array_to_json_array(&map_array).unwrap(), expected_json);
+ }
}