Skip to content

Commit c746cbf

Browse files
authored
Merge pull request #16 from qaspen-python/feature/from_serde_value_to_python_type
Added support for converting PostgreSQL JSON/JSONB into Python dict
2 parents 3e6dd94 + bf9daa1 commit c746cbf

File tree

1 file changed

+46
-2
lines changed

1 file changed

+46
-2
lines changed

src/value_converter.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ pub fn postgres_to_py(
473473
let db_json = row.try_get::<_, Option<Value>>(column_i)?;
474474

475475
match db_json {
476-
Some(value) => Ok(value.to_string().to_object(py)),
476+
Some(value) => Ok(build_python_from_serde_value(py, value)?),
477477
None => Ok(py.None().to_object(py)),
478478
}
479479
}
@@ -502,7 +502,7 @@ pub fn build_serde_value(value: &PyAny) -> RustPSQLDriverPyResult<Value> {
502502
result_vec.push(serde_value);
503503
} else {
504504
return Err(RustPSQLDriverError::PyToRustValueConversionError(
505-
"PyJSON/PyJSONB supports only list of lists or list of dicts.".to_string(),
505+
"PyJSON supports only list of lists or list of dicts.".to_string(),
506506
));
507507
}
508508
}
@@ -515,3 +515,47 @@ pub fn build_serde_value(value: &PyAny) -> RustPSQLDriverPyResult<Value> {
515515
));
516516
}
517517
}
518+
519+
/// Convert serde `Value` into Python object.
520+
/// # Errors
521+
/// May return Err Result if cannot add new value to Python Dict.
522+
pub fn build_python_from_serde_value(
523+
py: Python<'_>,
524+
value: Value,
525+
) -> RustPSQLDriverPyResult<Py<PyAny>> {
526+
match value {
527+
Value::Array(massive) => {
528+
let mut result_vec: Vec<Py<PyAny>> = vec![];
529+
530+
for single_record in massive {
531+
result_vec.push(build_python_from_serde_value(py, single_record)?);
532+
}
533+
534+
Ok(result_vec.to_object(py))
535+
}
536+
Value::Object(mapping) => {
537+
let py_dict = PyDict::new(py);
538+
539+
for (key, value) in mapping {
540+
py_dict.set_item(
541+
build_python_from_serde_value(py, Value::String(key))?,
542+
build_python_from_serde_value(py, value)?,
543+
)?;
544+
}
545+
546+
Ok(py_dict.to_object(py))
547+
}
548+
Value::Bool(boolean) => Ok(boolean.to_object(py)),
549+
Value::Number(number) => {
550+
if number.is_f64() {
551+
Ok(number.as_f64().to_object(py))
552+
} else if number.is_i64() {
553+
Ok(number.as_i64().to_object(py))
554+
} else {
555+
Ok(number.as_u64().to_object(py))
556+
}
557+
}
558+
Value::String(string) => Ok(string.to_object(py)),
559+
Value::Null => Ok(py.None()),
560+
}
561+
}

0 commit comments

Comments
 (0)