Skip to content

Commit df78688

Browse files
authored
Add preserve order on objects (#1)
* Add preserve order on objects * Add README
1 parent 93a173b commit df78688

File tree

5 files changed

+30
-23
lines changed

5 files changed

+30
-23
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# JMESPath for Rust
22

3+
## This fork preserves order
4+
5+
This is a fork of [jmespath.rs](https://github.com/jmespath/jmespath.rs) that
6+
preserves order. It is highly incompatible with the code upstream, probably
7+
someone who wants to take over and add this as a feature, this would be a nice
8+
addition to the library.
9+
10+
311
Rust implementation of [JMESPath](http://jmespath.org), a query language for JSON.
412

513
[Documentation](https://docs.rs/jmespath/)

jmespath/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ edition = "2018"
1414

1515
[dependencies]
1616
serde = { version = "1", features = ["rc"] }
17-
serde_json = "1"
17+
indexmap = {version = "1.9.1", features = ["serde-1"]}
18+
serde_json = { version = "1", features = ["preserve_order"] }
1819
lazy_static = "1.4"
1920

2021
[build-dependencies]

jmespath/src/functions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
//! JMESPath functions.
22
33
use std::cmp::{max, min};
4-
use std::collections::BTreeMap;
54
use std::fmt;
65

76
use crate::interpreter::{interpret, SearchResult};
87
use crate::variable::{JmespathType, Variable};
98
use crate::{Context, ErrorReason, JmespathError, Rcvar, RuntimeError};
9+
use indexmap::IndexMap;
1010
use serde_json::Number;
1111

1212
/// Represents a JMESPath function.
@@ -614,7 +614,7 @@ defn!(MergeFn, vec![arg!(object)], Some(arg!(object)));
614614
impl Function for MergeFn {
615615
fn evaluate(&self, args: &[Rcvar], ctx: &mut Context<'_>) -> SearchResult {
616616
self.signature.validate(args, ctx)?;
617-
let mut result = BTreeMap::new();
617+
let mut result = IndexMap::new();
618618
for arg in args {
619619
result.extend(
620620
arg.as_object()

jmespath/src/interpreter.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
//! Interprets JMESPath expressions.
22
3-
use std::collections::BTreeMap;
4-
53
use super::ast::Ast;
64
use super::variable::Variable;
75
use super::Context;
86
use super::{ErrorReason, JmespathError, Rcvar, RuntimeError};
7+
use indexmap::IndexMap;
98

109
/// Result of searching data using a JMESPath Expression.
1110
pub type SearchResult = Result<Rcvar, JmespathError>;
@@ -135,7 +134,7 @@ pub fn interpret(data: &Rcvar, node: &Ast, ctx: &mut Context<'_>) -> SearchResul
135134
if data.is_null() {
136135
Ok(Rcvar::new(Variable::Null))
137136
} else {
138-
let mut collected = BTreeMap::new();
137+
let mut collected = IndexMap::new();
139138
for kvp in elements {
140139
let value = interpret(data, &kvp.value, ctx)?;
141140
collected.insert(kvp.key.clone(), value);

jmespath/src/variable.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
//! Module for JMESPath runtime variables.
22
3+
use indexmap::IndexMap;
34
use serde::de::IntoDeserializer;
45
use serde::*;
56
use serde_json::error::Error;
67
use serde_json::value::Value;
78
use std::cmp::{max, Ordering};
8-
use std::collections::BTreeMap;
99
use std::fmt;
1010
use std::iter::Iterator;
1111
use std::string::ToString;
@@ -55,7 +55,7 @@ pub enum Variable {
5555
Bool(bool),
5656
Number(Number),
5757
Array(Vec<Rcvar>),
58-
Object(BTreeMap<String, Rcvar>),
58+
Object(IndexMap<String, Rcvar>),
5959
Expref(Ast),
6060
}
6161

@@ -180,7 +180,7 @@ fn convert_map<'a, T>(value: T) -> Result<Variable, JmespathError>
180180
where
181181
T: Iterator<Item = (&'a String, &'a Value)>,
182182
{
183-
let mut map: BTreeMap<String, Rcvar> = BTreeMap::new();
183+
let mut map: IndexMap<String, Rcvar> = IndexMap::new();
184184
for kvp in value {
185185
map.insert(kvp.0.to_owned(), kvp.1.to_jmespath()?);
186186
}
@@ -264,9 +264,9 @@ impl Variable {
264264
self.as_object().is_some()
265265
}
266266

267-
/// If the value is an Object, returns the associated BTreeMap.
267+
/// If the value is an Object, returns the associated IndexMap.
268268
/// Returns None otherwise.
269-
pub fn as_object(&self) -> Option<&BTreeMap<String, Rcvar>> {
269+
pub fn as_object(&self) -> Option<&IndexMap<String, Rcvar>> {
270270
match self {
271271
Variable::Object(map) => Some(map),
272272
_ => None,
@@ -604,7 +604,7 @@ impl<'de> de::Deserialize<'de> for Variable {
604604
where
605605
V: de::MapAccess<'de>,
606606
{
607-
let mut values = BTreeMap::new();
607+
let mut values = IndexMap::new();
608608

609609
while let Some((key, value)) = visitor.next_entry()? {
610610
values.insert(key, value);
@@ -868,7 +868,7 @@ impl<'de> de::SeqAccess<'de> for SeqDeserializer {
868868
}
869869

870870
struct MapDeserializer {
871-
iter: <BTreeMap<String, Rcvar> as IntoIterator>::IntoIter,
871+
iter: <IndexMap<String, Rcvar> as IntoIterator>::IntoIter,
872872
value: Option<Variable>,
873873
}
874874

@@ -959,12 +959,12 @@ pub struct TupleVariantState {
959959
#[doc(hidden)]
960960
pub struct StructVariantState {
961961
name: String,
962-
map: BTreeMap<String, Rcvar>,
962+
map: IndexMap<String, Rcvar>,
963963
}
964964

965965
#[doc(hidden)]
966966
pub struct MapState {
967-
map: BTreeMap<String, Rcvar>,
967+
map: IndexMap<String, Rcvar>,
968968
next_key: Option<String>,
969969
}
970970

@@ -1096,7 +1096,7 @@ impl ser::Serializer for Serializer {
10961096
where
10971097
T: ser::Serialize,
10981098
{
1099-
let mut values = BTreeMap::new();
1099+
let mut values = IndexMap::new();
11001100
values.insert(String::from(variant), Rcvar::new(to_variable(&value)?));
11011101
Ok(Variable::Object(values))
11021102
}
@@ -1141,7 +1141,7 @@ impl ser::Serializer for Serializer {
11411141

11421142
fn serialize_map(self, _len: Option<usize>) -> Result<MapState, Error> {
11431143
Ok(MapState {
1144-
map: BTreeMap::new(),
1144+
map: IndexMap::new(),
11451145
next_key: None,
11461146
})
11471147
}
@@ -1159,7 +1159,7 @@ impl ser::Serializer for Serializer {
11591159
) -> Result<StructVariantState, Error> {
11601160
Ok(StructVariantState {
11611161
name: String::from(variant),
1162-
map: BTreeMap::new(),
1162+
map: IndexMap::new(),
11631163
})
11641164
}
11651165
}
@@ -1226,7 +1226,7 @@ impl ser::SerializeTupleVariant for TupleVariantState {
12261226
}
12271227

12281228
fn end(self) -> Result<Variable, Error> {
1229-
let mut object = BTreeMap::new();
1229+
let mut object = IndexMap::new();
12301230
object.insert(self.name, Rcvar::new(Variable::Array(self.vec)));
12311231
Ok(Variable::Object(object))
12321232
}
@@ -1295,7 +1295,7 @@ impl ser::SerializeStructVariant for StructVariantState {
12951295
}
12961296

12971297
fn end(self) -> Result<Variable, Error> {
1298-
let mut object = BTreeMap::new();
1298+
let mut object = IndexMap::new();
12991299
object.insert(self.name, Rcvar::new(Variable::Object(self.map)));
13001300
Ok(Variable::Object(object))
13011301
}
@@ -1307,7 +1307,6 @@ mod tests {
13071307
use crate::ast::{Ast, Comparator};
13081308
use crate::Rcvar;
13091309
use serde_json::{self, Number, Value};
1310-
use std::collections::BTreeMap;
13111310

13121311
#[test]
13131312
fn creates_variable_from_str() {
@@ -1533,8 +1532,8 @@ mod tests {
15331532
#[test]
15341533
fn test_parses_json_object() {
15351534
let var = Variable::from_json("{\"a\": 1, \"b\": {\"c\": true}}").unwrap();
1536-
let mut expected = BTreeMap::new();
1537-
let mut sub_obj = BTreeMap::new();
1535+
let mut expected = IndexMap::new();
1536+
let mut sub_obj = IndexMap::new();
15381537
expected.insert(
15391538
"a".to_string(),
15401539
Rcvar::new(Variable::Number(Number::from_f64(1.0).unwrap())),

0 commit comments

Comments
 (0)