Skip to content

Commit

Permalink
Fixes #511: Allow deserialize_string for map fields originating from …
Browse files Browse the repository at this point in the history
…struct-formatted maps (#512)

* Fixes #511: Allow deserialize_string for map fields originating from struct-formatted maps

* Update CHANGELOG.md

Co-authored-by: Juniper Tyree <[email protected]>

* Fix code coverage in the test

* Fix formatting and add extra test

---------

Co-authored-by: Juniper Tyree <[email protected]>
  • Loading branch information
grindvoll and juntyr authored Oct 7, 2023
1 parent 1ff0efa commit 2f3e5a8
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix serialising reserved identifiers `true`, `false`, `Some`, `None`, `inf`[`f32`|`f64`], and `Nan`[`f32`|`f64`] ([#487](https://github.com/ron-rs/ron/pull/487))
- Disallow unclosed line comments at the end of `ron::value::RawValue` ([#489](https://github.com/ron-rs/ron/pull/489))
- Fix parsing of struct/variant names starting in `None`, `Some`, `true`, or `false` ([#499](https://github.com/ron-rs/ron/pull/499))
- Fix deserialising owned string field names in structs, allowing deserializing into `serde_json::Value`s ([#511](https://github.com/ron-rs/ron/pull/512))

### Miscellaneous

Expand Down
4 changes: 2 additions & 2 deletions src/de/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,11 @@ impl<'a, 'b: 'a, 'c> de::Deserializer<'b> for &'c mut Deserializer<'a, 'b> {
Err(Error::ExpectedIdentifier)
}

fn deserialize_string<V>(self, _: V) -> Result<V::Value>
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
Err(Error::ExpectedIdentifier)
self.deserialize_identifier(visitor)
}

fn deserialize_bytes<V>(self, _: V) -> Result<V::Value>
Expand Down
76 changes: 76 additions & 0 deletions tests/511_deserialize_any_map_string_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#[test]
fn test_map_custom_deserialize() {
use std::collections::HashMap;

#[derive(PartialEq, Debug)]
struct CustomMap(HashMap<String, String>);

// Use a custom deserializer for CustomMap in order to extract String
// keys in the visit_map method.
impl<'de> serde::de::Deserialize<'de> for CustomMap {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct CVisitor;
impl<'de> serde::de::Visitor<'de> for CVisitor {
type Value = CustomMap;

// GRCOV_EXCL_START
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "a map with string keys and values")
}
// GRCOV_EXCL_STOP

fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let mut inner = HashMap::new();
while let Some((k, v)) = map.next_entry::<String, String>()? {
inner.insert(k, v);
}
Ok(CustomMap(inner))
}
}
// Note: This method will try to deserialize any value. In this test, it will
// invoke the visit_map method in the visitor.
deserializer.deserialize_any(CVisitor)
}
}

let mut map = HashMap::<String, String>::new();
map.insert("key1".into(), "value1".into());
map.insert("key2".into(), "value2".into());

let result: Result<CustomMap, _> = ron::from_str(
r#"(
key1: "value1",
key2: "value2",
)"#,
);

assert_eq!(result, Ok(CustomMap(map)));
}

#[test]
fn test_ron_struct_as_json_map() {
let json: serde_json::Value = ron::from_str("(f1: 0, f2: 1)").unwrap();
assert_eq!(
json,
serde_json::Value::Object(
[
(
String::from("f1"),
serde_json::Value::Number(serde_json::Number::from(0))
),
(
String::from("f2"),
serde_json::Value::Number(serde_json::Number::from(1))
),
]
.into_iter()
.collect()
)
);
}
6 changes: 5 additions & 1 deletion tests/non_identifier_identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,11 @@ test_non_identifier! { test_u128 => deserialize_u128() }
test_non_identifier! { test_f32 => deserialize_f32() }
test_non_identifier! { test_f64 => deserialize_f64() }
test_non_identifier! { test_char => deserialize_char() }
test_non_identifier! { test_string => deserialize_string() }
// Removed due to fix for #511 - string keys are allowed.
// test_non_identifier! { test_string => deserialize_string() }
// See comment above. If deserialize_str is to be added, it should give the same expected result as
// deserialize_string. deserialize_str and deserialize_string should be consistently implemented.
// test_non_identifier! { test_str => deserialize_str() }
test_non_identifier! { test_bytes => deserialize_bytes() }
test_non_identifier! { test_byte_buf => deserialize_byte_buf() }
test_non_identifier! { test_option => deserialize_option() }
Expand Down

0 comments on commit 2f3e5a8

Please sign in to comment.