diff --git a/core/json/de.rs b/core/json/de.rs index 14927bb18..91932e199 100644 --- a/core/json/de.rs +++ b/core/json/de.rs @@ -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(pairs: &Vec<(String, Val)>, serializer: S) -> Result + 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, 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(self, mut access: M) -> Result + 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) + } +} diff --git a/core/json/mod.rs b/core/json/mod.rs index 10e682148..07820e480 100644 --- a/core/json/mod.rs +++ b/core/json/mod.rs @@ -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), - Object(IndexMap), + #[serde(with = "ordered_object")] + Object(Vec<(String, Val)>), } pub fn get_json(json_value: &OwnedValue) -> crate::Result { @@ -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);