use crate::core::{FieldSchema, FieldType};
pub(crate) fn json_bool(v: &serde_json::Value) -> Option<bool> {
v.as_bool().or_else(|| v.as_i64().map(|n| n != 0))
}
pub(crate) fn render_value_for_input_json(row: &serde_json::Value, field: &FieldSchema) -> String {
let v = row.get(field.column).or_else(|| row.get(field.name));
let Some(v) = v else { return String::new() };
if v.is_null() {
return String::new();
}
match field.ty {
FieldType::I16 | FieldType::I32 | FieldType::I64 => v
.as_i64()
.map(|n| n.to_string())
.unwrap_or_else(|| v.as_str().unwrap_or("").to_owned()),
FieldType::F32 | FieldType::F64 => v
.as_f64()
.map(|n| n.to_string())
.unwrap_or_else(|| v.as_str().unwrap_or("").to_owned()),
FieldType::Bool => json_bool(v)
.map(|b| b.to_string())
.unwrap_or_else(|| v.as_str().unwrap_or("").to_owned()),
FieldType::String | FieldType::Uuid => v.as_str().unwrap_or("").to_owned(),
FieldType::Date => v.as_str().unwrap_or("").to_owned(),
FieldType::Time => {
let s = v.as_str().unwrap_or("");
match chrono::NaiveTime::parse_from_str(s, "%H:%M:%S%.f") {
Ok(t) if chrono::Timelike::nanosecond(&t) != 0 => {
t.format("%H:%M:%S%.3f").to_string()
}
_ => s.to_owned(),
}
}
FieldType::DateTime => {
let s = v.as_str().unwrap_or("");
if s.len() >= 19 {
s[..19].to_owned()
} else {
s.to_owned()
}
}
FieldType::Json => {
if !field.nullable && v == &serde_json::Value::Object(serde_json::Map::new()) {
String::new()
} else {
serde_json::to_string_pretty(v).unwrap_or_default()
}
}
FieldType::Decimal | FieldType::Binary => v.as_str().unwrap_or("").to_owned(),
FieldType::Array(_) => v.as_array().map_or_else(
|| v.to_string(),
|items| {
items
.iter()
.map(|i| i.as_str().map_or_else(|| i.to_string(), str::to_owned))
.collect::<Vec<_>>()
.join(", ")
},
),
FieldType::Range(_) => v.as_str().map_or_else(|| v.to_string(), str::to_owned),
FieldType::HStore => v.to_string(),
FieldType::Vector(_) => v.to_string(),
FieldType::Geometry(_) => v.to_string(),
}
}