mirror of
https://github.com/neondatabase/neon.git
synced 2026-01-15 09:22:55 +00:00
turns out we don't actually need to deser everything
This commit is contained in:
@@ -20,14 +20,14 @@ pub(crate) fn json_to_pg_text(
|
||||
}
|
||||
|
||||
fn json_value_to_pg_text(value: &RawValue) -> Result<Option<String>, serde_json::Error> {
|
||||
let value = serde_json::from_str(value.get())?;
|
||||
match value {
|
||||
let lazy_value = serde_json::from_str(value.get())?;
|
||||
match lazy_value {
|
||||
// special care for nulls
|
||||
LazyValue::Null => Ok(None),
|
||||
|
||||
// convert to text with escaping
|
||||
v @ (LazyValue::Bool(_) | LazyValue::Number(_) | LazyValue::Object(_)) => {
|
||||
Ok(Some(v.to_string()))
|
||||
LazyValue::Bool | LazyValue::Number | LazyValue::Object => {
|
||||
Ok(Some(value.get().to_string()))
|
||||
}
|
||||
|
||||
// avoid escaping here, as we pass this as a parameter
|
||||
@@ -46,7 +46,7 @@ fn json_value_to_pg_text(value: &RawValue) -> Result<Option<String>, serde_json:
|
||||
//
|
||||
// Example of the same escaping in node-postgres: packages/pg/lib/utils.js
|
||||
//
|
||||
fn json_array_to_pg_array(arr: Vec<&RawValue>) -> Result<String, serde_json::Error> {
|
||||
fn json_array_to_pg_array(arr: Vec<&RawValue>) -> Result<String, serde_json::Error> {
|
||||
let mut output = String::new();
|
||||
let mut first = true;
|
||||
|
||||
@@ -68,17 +68,17 @@ fn json_array_to_pg_array(arr: Vec<&RawValue>) -> Result<String, serde_json::Er
|
||||
}
|
||||
|
||||
fn json_array_to_pg_array_inner(value: &RawValue) -> Result<Option<String>, serde_json::Error> {
|
||||
let value = serde_json::from_str(value.get())?;
|
||||
match value {
|
||||
let lazy_value = serde_json::from_str(value.get())?;
|
||||
match lazy_value {
|
||||
// special care for nulls
|
||||
LazyValue::Null => Ok(None),
|
||||
|
||||
// convert to text with escaping
|
||||
// here string needs to be escaped, as it is part of the array
|
||||
v @ (LazyValue::Bool(_) | LazyValue::Number(_) | LazyValue::String(_)) => {
|
||||
Ok(Some(v.to_string()))
|
||||
LazyValue::Bool | LazyValue::Number | LazyValue::String(_) => {
|
||||
Ok(Some(value.get().to_string()))
|
||||
}
|
||||
v @ LazyValue::Object(_) => Ok(Some(json!(v.to_string()).to_string())),
|
||||
LazyValue::Object => Ok(Some(json!(value.get().to_string()).to_string())),
|
||||
|
||||
// recurse into array
|
||||
LazyValue::Array(arr) => Ok(Some(json_array_to_pg_array(arr)?)),
|
||||
|
||||
@@ -8,20 +8,19 @@
|
||||
use core::fmt;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use serde::{
|
||||
de::{MapAccess, SeqAccess, Visitor},
|
||||
Deserialize, Serialize,
|
||||
de::{IgnoredAny, MapAccess, SeqAccess, Visitor},
|
||||
Deserialize,
|
||||
};
|
||||
use serde_json::{value::RawValue, Number};
|
||||
use serde_json::value::RawValue;
|
||||
|
||||
pub enum LazyValue<'de> {
|
||||
Null,
|
||||
Bool(bool),
|
||||
Number(Number),
|
||||
Bool,
|
||||
Number,
|
||||
String(Cow<'de, str>),
|
||||
Array(Vec<&'de RawValue>),
|
||||
Object(IndexMap<String, &'de RawValue>),
|
||||
Object,
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for LazyValue<'de> {
|
||||
@@ -40,23 +39,23 @@ impl<'de> Deserialize<'de> for LazyValue<'de> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_bool<E>(self, value: bool) -> Result<LazyValue<'de>, E> {
|
||||
Ok(LazyValue::Bool(value))
|
||||
fn visit_bool<E>(self, _value: bool) -> Result<LazyValue<'de>, E> {
|
||||
Ok(LazyValue::Bool)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_i64<E>(self, value: i64) -> Result<LazyValue<'de>, E> {
|
||||
Ok(LazyValue::Number(value.into()))
|
||||
fn visit_i64<E>(self, _value: i64) -> Result<LazyValue<'de>, E> {
|
||||
Ok(LazyValue::Number)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_u64<E>(self, value: u64) -> Result<LazyValue<'de>, E> {
|
||||
Ok(LazyValue::Number(value.into()))
|
||||
fn visit_u64<E>(self, _value: u64) -> Result<LazyValue<'de>, E> {
|
||||
Ok(LazyValue::Number)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_f64<E>(self, value: f64) -> Result<LazyValue<'de>, E> {
|
||||
Ok(Number::from_f64(value).map_or(LazyValue::Null, LazyValue::Number))
|
||||
fn visit_f64<E>(self, _value: f64) -> Result<LazyValue<'de>, E> {
|
||||
Ok(LazyValue::Number)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -116,13 +115,8 @@ impl<'de> Deserialize<'de> for LazyValue<'de> {
|
||||
where
|
||||
V: MapAccess<'de>,
|
||||
{
|
||||
let mut values = IndexMap::new();
|
||||
|
||||
while let Some((key, value)) = visitor.next_entry()? {
|
||||
values.insert(key, value);
|
||||
}
|
||||
|
||||
Ok(LazyValue::Object(values))
|
||||
while visitor.next_entry::<IgnoredAny, IgnoredAny>()?.is_some() {}
|
||||
Ok(LazyValue::Object)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,37 +124,6 @@ impl<'de> Deserialize<'de> for LazyValue<'de> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for LazyValue<'_> {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ::serde::Serializer,
|
||||
{
|
||||
match self {
|
||||
LazyValue::Null => serializer.serialize_unit(),
|
||||
LazyValue::Bool(b) => serializer.serialize_bool(*b),
|
||||
LazyValue::Number(n) => n.serialize(serializer),
|
||||
LazyValue::String(s) => serializer.serialize_str(s),
|
||||
LazyValue::Array(v) => v.serialize(serializer),
|
||||
LazyValue::Object(m) => {
|
||||
use serde::ser::SerializeMap;
|
||||
let mut map = serializer.serialize_map(Some(m.len()))?;
|
||||
for (k, v) in m {
|
||||
map.serialize_entry(k, v)?;
|
||||
}
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::to_string_trait_impl)]
|
||||
impl ToString for LazyValue<'_> {
|
||||
fn to_string(&self) -> String {
|
||||
serde_json::to_string(self).expect("json encoding a LazyValue should never error")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::borrow::Cow;
|
||||
@@ -181,13 +144,9 @@ mod tests {
|
||||
|
||||
let lazy: LazyValue = serde_json::from_str(&json).unwrap();
|
||||
|
||||
let LazyValue::Object(object) = lazy else {
|
||||
let LazyValue::Object = lazy else {
|
||||
panic!("expected object")
|
||||
};
|
||||
assert_eq!(object.len(), 2);
|
||||
|
||||
assert_eq!(object["foo"].get(), r#"{"bar":1}"#);
|
||||
assert_eq!(object["baz"].get(), r#"[2,3]"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user