postrust_core/
row_json.rs1pub fn row_to_json(row: &sqlx::postgres::PgRow) -> serde_json::Value {
15 use sqlx::{Column, Row, TypeInfo};
16
17 let mut map = serde_json::Map::new();
18
19 for column in row.columns() {
20 let name = column.name();
21 let type_name = column.type_info().name();
22
23 let value = match type_name {
24 "INT2" | "SMALLINT" => row
25 .try_get::<i16, _>(name)
26 .ok()
27 .map(|v| serde_json::Value::Number(v.into())),
28 "INT4" | "INT" | "INTEGER" => row
29 .try_get::<i32, _>(name)
30 .ok()
31 .map(|v| serde_json::Value::Number(v.into())),
32 "INT8" | "BIGINT" => row
33 .try_get::<i64, _>(name)
34 .ok()
35 .map(|v| serde_json::Value::Number(v.into())),
36 "FLOAT4" | "REAL" => row
37 .try_get::<f32, _>(name)
38 .ok()
39 .and_then(|v| serde_json::Number::from_f64(v as f64))
40 .map(serde_json::Value::Number),
41 "FLOAT8" | "DOUBLE PRECISION" => row
42 .try_get::<f64, _>(name)
43 .ok()
44 .and_then(serde_json::Number::from_f64)
45 .map(serde_json::Value::Number),
46 "NUMERIC" | "DECIMAL" => {
55 row.try_get::<sqlx::types::BigDecimal, _>(name)
56 .ok()
57 .map(|v| {
58 let text = v.to_string();
59 serde_json::from_str::<serde_json::Value>(&text)
60 .ok()
61 .filter(serde_json::Value::is_number)
62 .unwrap_or(serde_json::Value::String(text))
63 })
64 }
65 "BOOL" | "BOOLEAN" => row
66 .try_get::<bool, _>(name)
67 .ok()
68 .map(serde_json::Value::Bool),
69 "JSON" | "JSONB" => row.try_get::<serde_json::Value, _>(name).ok(),
70 "UUID" => row
71 .try_get::<sqlx::types::Uuid, _>(name)
72 .ok()
73 .map(|v| serde_json::Value::String(v.to_string())),
74 "TIMESTAMPTZ" | "TIMESTAMP WITH TIME ZONE" => row
75 .try_get::<chrono::DateTime<chrono::Utc>, _>(name)
76 .ok()
77 .map(|v| serde_json::Value::String(v.to_rfc3339())),
78 "TIMESTAMP" | "TIMESTAMP WITHOUT TIME ZONE" => row
79 .try_get::<chrono::NaiveDateTime, _>(name)
80 .ok()
81 .map(|v| serde_json::Value::String(v.to_string())),
82 "DATE" => row
83 .try_get::<chrono::NaiveDate, _>(name)
84 .ok()
85 .map(|v| serde_json::Value::String(v.to_string())),
86 "TIME" | "TIME WITHOUT TIME ZONE" => row
87 .try_get::<chrono::NaiveTime, _>(name)
88 .ok()
89 .map(|v| serde_json::Value::String(v.to_string())),
90 _ => row
91 .try_get::<String, _>(name)
92 .ok()
93 .map(serde_json::Value::String),
94 };
95
96 map.insert(name.to_string(), value.unwrap_or(serde_json::Value::Null));
97 }
98
99 serde_json::Value::Object(map)
100}