parquet_variant_compute/
to_json.rs1use crate::VariantArray;
8use arrow::array::{ArrayRef, BooleanBufferBuilder, StringArray};
9use arrow::buffer::{Buffer, NullBuffer, OffsetBuffer, ScalarBuffer};
10use arrow_schema::ArrowError;
11use parquet_variant_json::VariantToJson;
12
13pub fn variant_to_json(input: &ArrayRef) -> Result<StringArray, ArrowError> {
15 let array = VariantArray::try_new(input)?;
16
17 let mut json_buffer: Vec<u8> = Vec::with_capacity(array.len() * 128);
21 let mut offsets: Vec<i32> = Vec::with_capacity(array.len() + 1);
22 let mut validity = BooleanBufferBuilder::new(array.len());
23 let mut current_offset: i32 = 0;
24 offsets.push(current_offset);
25
26 for i in 0..array.len() {
27 if array.is_null(i) {
28 validity.append(false);
29 offsets.push(current_offset);
30 } else {
31 let variant = array.try_value(i)?;
32 let start_len = json_buffer.len();
33 variant.to_json(&mut json_buffer)?;
34 let written = (json_buffer.len() - start_len) as i32;
35 current_offset += written;
36 offsets.push(current_offset);
37 validity.append(true);
38 }
39 }
40
41 let offsets_buffer = OffsetBuffer::new(ScalarBuffer::from(offsets));
42 let value_buffer = Buffer::from_vec(json_buffer);
43 let null_buffer = NullBuffer::new(validity.finish());
44
45 StringArray::try_new(offsets_buffer, value_buffer, Some(null_buffer))
46}
47
48#[cfg(test)]
49mod test {
50 use crate::variant_to_json;
51 use arrow::array::{Array, ArrayRef, BinaryBuilder, BooleanBufferBuilder, StructArray};
52 use arrow::buffer::NullBuffer;
53 use arrow::datatypes::DataType;
54 use arrow::datatypes::Field;
55 use arrow_schema::Fields;
56 use std::sync::Arc;
57
58 #[test]
59 fn test_variant_to_json() {
60 let mut metadata_builder = BinaryBuilder::new();
61 let mut value_builder = BinaryBuilder::new();
62
63 metadata_builder.append_value([1, 0, 0]);
65 value_builder.append_value([12, 0]);
66
67 metadata_builder.append_null();
69 value_builder.append_null();
70
71 metadata_builder.append_value([1, 1, 0, 1, 97]);
73 value_builder.append_value([2, 1, 0, 0, 2, 12, 32]);
74
75 metadata_builder.append_value([1, 0, 0]);
77 value_builder.append_value([0]);
78
79 metadata_builder.append_null();
81 value_builder.append_null();
82
83 let metadata_array = Arc::new(metadata_builder.finish()) as ArrayRef;
84 let value_array = Arc::new(value_builder.finish()) as ArrayRef;
85
86 let fields: Fields = vec![
87 Field::new("metadata", DataType::Binary, true),
88 Field::new("value", DataType::Binary, true),
89 ]
90 .into();
91
92 let mut validity = BooleanBufferBuilder::new(value_array.len());
93 for i in 0..value_array.len() {
94 let is_valid = value_array.is_valid(i) && metadata_array.is_valid(i);
95 validity.append(is_valid);
96 }
97 let null_buffer = NullBuffer::new(validity.finish());
98
99 let struct_array = StructArray::new(
100 fields,
101 vec![metadata_array.clone(), value_array.clone()],
102 Some(null_buffer), );
104
105 let input = Arc::new(struct_array) as ArrayRef;
106
107 let result = variant_to_json(&input).unwrap();
108
109 let expected = vec![Some("0"), None, Some("{\"a\":32}"), Some("null"), None];
111
112 let result_vec: Vec<Option<&str>> = (0..result.len())
113 .map(|i| {
114 if result.is_null(i) {
115 None
116 } else {
117 Some(result.value(i))
118 }
119 })
120 .collect();
121
122 assert_eq!(result_vec, expected);
123 }
124}