add deserialization patch to represent obj as ordered Vec and preserve duplicates

This commit is contained in:
Ihor Andrianov
2025-01-28 19:58:48 +02:00
parent ef6a1be335
commit f97d085934
2 changed files with 57 additions and 2 deletions

View File

@@ -504,3 +504,56 @@ impl<'de> de::VariantAccess<'de> for Variant<'de> {
}
}
}
pub mod ordered_object {
use crate::json::Val;
use serde::de::{MapAccess, Visitor};
use serde::{Deserializer, Serializer};
use std::fmt;
pub fn serialize<S>(pairs: &Vec<(String, Val)>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::SerializeMap;
let mut map = serializer.serialize_map(Some(pairs.len()))?;
for (k, v) in pairs {
map.serialize_entry(k, v)?;
}
map.end()
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<(String, Val)>, D::Error>
where
D: Deserializer<'de>,
{
struct OrderedMapVisitor;
impl<'de> Visitor<'de> for OrderedMapVisitor {
type Value = Vec<(String, Val)>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a map")
}
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
where
M: MapAccess<'de>,
{
let mut pairs = match access.size_hint() {
Some(size) => Vec::with_capacity(size),
None => Vec::new(),
};
while let Some((key, value)) = access.next_entry()? {
pairs.push((key, value));
}
Ok(pairs)
}
}
deserializer.deserialize_map(OrderedMapVisitor)
}
}

View File

@@ -6,6 +6,7 @@ mod ser;
use std::rc::Rc;
pub use crate::json::de::from_str;
use crate::json::de::ordered_object;
use crate::json::error::Error as JsonError;
use crate::json::json_path::{json_path, JsonPath, PathElement};
pub use crate::json::ser::to_string;
@@ -23,7 +24,8 @@ pub enum Val {
Float(f64),
String(String),
Array(Vec<Val>),
Object(IndexMap<String, Val>),
#[serde(with = "ordered_object")]
Object(Vec<(String, Val)>),
}
pub fn get_json(json_value: &OwnedValue) -> crate::Result<OwnedValue> {
@@ -367,7 +369,7 @@ fn json_extract_single<'a>(
match current_element {
Val::Object(map) => {
if let Some(value) = map.get(key) {
if let Some((_, value)) = map.iter().find(|(k, _)| k == key) {
current_element = value;
} else {
return Ok(None);