Skip to content

Instantly share code, notes, and snippets.

@kubo
Created January 17, 2024 12:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kubo/6dab10dee8419268cc101bbfbba23456 to your computer and use it in GitHub Desktop.
Save kubo/6dab10dee8419268cc101bbfbba23456 to your computer and use it in GitHub Desktop.
fetch rows as serde_json::Value
use oracle::{sql_type::OracleType, sql_type::ToSql, Connection, ResultSet, Row};
use std::str::FromStr;
// Usage:
//
// // conn is oracle::Connection.
// for json_result in query_as_json(&conn, sql, &[])? {
// // json_result is std::result::Result<serde_json::Value, oracle::Error>.
// let json = json_result?;
// println!("{}", json);
// }
pub fn query_as_json<'a>(
conn: &'a Connection,
sql: &str,
params: &[&dyn ToSql],
) -> oracle::Result<JsonRowIterator<'a>> {
Ok(JsonRowIterator::new(conn.query(sql, params)?))
}
pub struct JsonRowIterator<'a> {
result_set: ResultSet<'a, Row>,
}
impl<'a> JsonRowIterator<'a> {
fn new(rs: ResultSet<'a, Row>) -> JsonRowIterator<'a> {
JsonRowIterator { result_set: rs }
}
fn json_from_row(&self, row: Row) -> oracle::Result<serde_json::Value> {
let mut map = serde_json::Map::new();
for (pos, colinfo) in self.result_set.column_info().iter().enumerate() {
let value = match colinfo.oracle_type() {
OracleType::BinaryFloat
| OracleType::BinaryDouble
| OracleType::Number(_, _)
| OracleType::Float(_) => row.get::<usize, Option<String>>(pos)?.map(|val| {
match serde_json::Number::from_str(&val) {
Ok(num) => serde_json::Value::Number(num),
Err(_) => serde_json::Value::String(val),
}
}),
_ => row
.get::<usize, Option<String>>(pos)?
.map(serde_json::Value::String),
};
map.insert(
colinfo.name().into(),
value.unwrap_or(serde_json::Value::Null),
);
}
Ok(serde_json::Value::Object(map))
}
}
impl<'a> Iterator for JsonRowIterator<'a> {
type Item = oracle::Result<serde_json::Value>;
fn next(&mut self) -> Option<Self::Item> {
let row_result = self.result_set.next()?;
Some(row_result.and_then(|row| self.json_from_row(row)))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment