use serde::de::{DeserializeSeed, Deserializer, SeqAccess, Visitor};
use serde_json::Value;
use std::fmt;
use std::marker::PhantomData;
pub fn to_row_major<'de, D>(deserializer: D) -> Result<Vec<Vec<Value>>, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(DataVisitor)
}
pub fn to_row_major_option<'de, D>(deserializer: D) -> Result<Option<Vec<Vec<Value>>>, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_option(OptionDataVisitor)
}
struct OptionDataVisitor;
impl<'de> Visitor<'de> for OptionDataVisitor {
type Value = Option<Vec<Vec<Value>>>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("null or column-major data array")
}
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(None)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
to_row_major(deserializer).map(Some)
}
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(None)
}
}
struct DataVisitor;
impl<'de> Visitor<'de> for DataVisitor {
type Value = Vec<Vec<Value>>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("column-major data array")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut rows: Vec<Vec<Value>> = Vec::new();
let mut col_idx = 0;
while let Some(()) = seq.next_element_seed(ColumnSeed {
rows: &mut rows,
col_idx,
_marker: PhantomData,
})? {
col_idx += 1;
}
Ok(rows)
}
}
struct ColumnSeed<'a, 'de> {
rows: &'a mut Vec<Vec<Value>>,
col_idx: usize,
_marker: PhantomData<&'de ()>,
}
impl<'de, 'a> DeserializeSeed<'de> for ColumnSeed<'a, 'de> {
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(ColumnVisitor {
rows: self.rows,
col_idx: self.col_idx,
})
}
}
struct ColumnVisitor<'a> {
rows: &'a mut Vec<Vec<Value>>,
col_idx: usize,
}
impl<'de, 'a> Visitor<'de> for ColumnVisitor<'a> {
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("array of column values")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut row_idx = 0;
while let Some(value) = seq.next_element::<Value>()? {
if self.col_idx == 0 {
self.rows.push(vec![value]);
} else {
if row_idx < self.rows.len() {
self.rows[row_idx].push(value);
} else {
let mut new_row = vec![Value::Null; self.col_idx];
new_row.push(value);
self.rows.push(new_row);
}
}
row_idx += 1;
}
while row_idx < self.rows.len() {
self.rows[row_idx].push(Value::Null);
row_idx += 1;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde::Deserialize;
use serde_json::json;
#[derive(Debug, Deserialize)]
struct TestData {
#[serde(deserialize_with = "to_row_major")]
data: Vec<Vec<Value>>,
}
#[derive(Debug, Deserialize)]
struct TestDataOption {
#[serde(deserialize_with = "to_row_major_option")]
data: Option<Vec<Vec<Value>>>,
}
#[test]
fn test_empty_data() {
let json = json!({ "data": [] });
let result: TestData = serde_json::from_value(json).unwrap();
assert!(result.data.is_empty());
}
#[test]
fn test_single_column_single_row() {
let json = json!({ "data": [[42]] });
let result: TestData = serde_json::from_value(json).unwrap();
assert_eq!(result.data.len(), 1);
assert_eq!(result.data[0].len(), 1);
assert_eq!(result.data[0][0], json!(42));
}
#[test]
fn test_single_column_multiple_rows() {
let json = json!({ "data": [[1, 2, 3]] });
let result: TestData = serde_json::from_value(json).unwrap();
assert_eq!(result.data.len(), 3);
assert_eq!(result.data[0], vec![json!(1)]);
assert_eq!(result.data[1], vec![json!(2)]);
assert_eq!(result.data[2], vec![json!(3)]);
}
#[test]
fn test_multiple_columns_single_row() {
let json = json!({ "data": [[1], ["a"]] });
let result: TestData = serde_json::from_value(json).unwrap();
assert_eq!(result.data.len(), 1);
assert_eq!(result.data[0], vec![json!(1), json!("a")]);
}
#[test]
fn test_multiple_columns_multiple_rows() {
let json = json!({ "data": [[1, 2, 3], ["a", "b", "c"]] });
let result: TestData = serde_json::from_value(json).unwrap();
assert_eq!(result.data.len(), 3);
assert_eq!(result.data[0], vec![json!(1), json!("a")]);
assert_eq!(result.data[1], vec![json!(2), json!("b")]);
assert_eq!(result.data[2], vec![json!(3), json!("c")]);
}
#[test]
fn test_with_null_values() {
let json = json!({ "data": [[1, null, 3], [null, "b", "c"]] });
let result: TestData = serde_json::from_value(json).unwrap();
assert_eq!(result.data.len(), 3);
assert_eq!(result.data[0], vec![json!(1), Value::Null]);
assert_eq!(result.data[1], vec![Value::Null, json!("b")]);
assert_eq!(result.data[2], vec![json!(3), json!("c")]);
}
#[test]
fn test_mixed_types() {
let json = json!({ "data": [[1, 2], [true, false], ["x", "y"], [1.5, 2.5]] });
let result: TestData = serde_json::from_value(json).unwrap();
assert_eq!(result.data.len(), 2);
assert_eq!(
result.data[0],
vec![json!(1), json!(true), json!("x"), json!(1.5)]
);
assert_eq!(
result.data[1],
vec![json!(2), json!(false), json!("y"), json!(2.5)]
);
}
#[test]
fn test_option_none() {
let json = json!({ "data": null });
let result: TestDataOption = serde_json::from_value(json).unwrap();
assert!(result.data.is_none());
}
#[test]
fn test_option_some_empty() {
let json = json!({ "data": [] });
let result: TestDataOption = serde_json::from_value(json).unwrap();
assert_eq!(result.data, Some(vec![]));
}
#[test]
fn test_option_some_with_data() {
let json = json!({ "data": [[1, 2], ["a", "b"]] });
let result: TestDataOption = serde_json::from_value(json).unwrap();
let data = result.data.unwrap();
assert_eq!(data.len(), 2);
assert_eq!(data[0], vec![json!(1), json!("a")]);
assert_eq!(data[1], vec![json!(2), json!("b")]);
}
#[test]
fn test_large_dataset() {
let num_rows = 1000;
let num_cols = 10;
let columns: Vec<Vec<i32>> = (0..num_cols)
.map(|col| {
(0..num_rows)
.map(|row| (row * num_cols + col) as i32)
.collect()
})
.collect();
let json = json!({ "data": columns });
let result: TestData = serde_json::from_value(json).unwrap();
assert_eq!(result.data.len(), num_rows);
for row in &result.data {
assert_eq!(row.len(), num_cols);
}
assert_eq!(result.data[0][0], json!(0)); assert_eq!(result.data[0][1], json!(1)); assert_eq!(result.data[1][0], json!(10)); assert_eq!(result.data[999][9], json!(9999)); }
#[test]
fn test_realistic_exasol_response() {
let json = json!({
"data": [
[1, 2, 3], ["Alice", "Bob", "Carol"], [true, false, true], ["2024-01-15", "2024-02-20", null], [1234.56, 7890.12, 0.0] ]
});
let result: TestData = serde_json::from_value(json).unwrap();
assert_eq!(result.data.len(), 3);
assert_eq!(result.data[0][0], json!(1));
assert_eq!(result.data[0][1], json!("Alice"));
assert_eq!(result.data[0][2], json!(true));
assert_eq!(result.data[0][3], json!("2024-01-15"));
assert_eq!(result.data[0][4], json!(1234.56));
assert_eq!(result.data[1][0], json!(2));
assert_eq!(result.data[1][1], json!("Bob"));
assert_eq!(result.data[2][0], json!(3));
assert_eq!(result.data[2][3], Value::Null); }
}