Skip to content

Commit 59d9f96

Browse files
authored
Merge pull request #1055 from dtolnay/boolkey
Support bool in map keys
2 parents 8652bf2 + 9b69f16 commit 59d9f96

File tree

5 files changed

+79
-18
lines changed

5 files changed

+79
-18
lines changed

src/de.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2203,6 +2203,41 @@ where
22032203
deserialize_numeric_key!(deserialize_f32, deserialize_f32);
22042204
deserialize_numeric_key!(deserialize_f64);
22052205

2206+
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
2207+
where
2208+
V: de::Visitor<'de>,
2209+
{
2210+
self.de.eat_char();
2211+
2212+
let peek = match tri!(self.de.next_char()) {
2213+
Some(b) => b,
2214+
None => {
2215+
return Err(self.de.peek_error(ErrorCode::EofWhileParsingValue));
2216+
}
2217+
};
2218+
2219+
let value = match peek {
2220+
b't' => {
2221+
tri!(self.de.parse_ident(b"rue\""));
2222+
visitor.visit_bool(true)
2223+
}
2224+
b'f' => {
2225+
tri!(self.de.parse_ident(b"alse\""));
2226+
visitor.visit_bool(false)
2227+
}
2228+
_ => {
2229+
self.de.scratch.clear();
2230+
let s = tri!(self.de.read.parse_str(&mut self.de.scratch));
2231+
Err(de::Error::invalid_type(Unexpected::Str(&s), &visitor))
2232+
}
2233+
};
2234+
2235+
match value {
2236+
Ok(value) => Ok(value),
2237+
Err(err) => Err(self.de.fix_position(err)),
2238+
}
2239+
}
2240+
22062241
#[inline]
22072242
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
22082243
where
@@ -2258,7 +2293,7 @@ where
22582293
}
22592294

22602295
forward_to_deserialize_any! {
2261-
bool char str string unit unit_struct seq tuple tuple_struct map struct
2296+
char str string unit unit_struct seq tuple tuple_struct map struct
22622297
identifier ignored_any
22632298
}
22642299
}

src/ser.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -827,8 +827,21 @@ where
827827
type SerializeStruct = Impossible<(), Error>;
828828
type SerializeStructVariant = Impossible<(), Error>;
829829

830-
fn serialize_bool(self, _value: bool) -> Result<()> {
831-
Err(key_must_be_a_string())
830+
fn serialize_bool(self, value: bool) -> Result<()> {
831+
tri!(self
832+
.ser
833+
.formatter
834+
.begin_string(&mut self.ser.writer)
835+
.map_err(Error::io));
836+
tri!(self
837+
.ser
838+
.formatter
839+
.write_bool(&mut self.ser.writer, value)
840+
.map_err(Error::io));
841+
self.ser
842+
.formatter
843+
.end_string(&mut self.ser.writer)
844+
.map_err(Error::io)
832845
}
833846

834847
fn serialize_i8(self, value: i8) -> Result<()> {

src/value/de.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,22 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> {
11831183
deserialize_numeric_key!(deserialize_i128, do_deserialize_i128);
11841184
deserialize_numeric_key!(deserialize_u128, do_deserialize_u128);
11851185

1186+
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Error>
1187+
where
1188+
V: Visitor<'de>,
1189+
{
1190+
if self.key == "true" {
1191+
visitor.visit_bool(true)
1192+
} else if self.key == "false" {
1193+
visitor.visit_bool(false)
1194+
} else {
1195+
Err(serde::de::Error::invalid_type(
1196+
Unexpected::Str(&self.key),
1197+
&visitor,
1198+
))
1199+
}
1200+
}
1201+
11861202
#[inline]
11871203
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
11881204
where
@@ -1219,8 +1235,8 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> {
12191235
}
12201236

12211237
forward_to_deserialize_any! {
1222-
bool char str string bytes byte_buf unit unit_struct seq tuple
1223-
tuple_struct map struct identifier ignored_any
1238+
char str string bytes byte_buf unit unit_struct seq tuple tuple_struct
1239+
map struct identifier ignored_any
12241240
}
12251241
}
12261242

src/value/ser.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,8 @@ impl serde::Serializer for MapKeySerializer {
483483
value.serialize(self)
484484
}
485485

486-
fn serialize_bool(self, _value: bool) -> Result<String> {
487-
Err(key_must_be_a_string())
486+
fn serialize_bool(self, value: bool) -> Result<String> {
487+
Ok(value.to_string())
488488
}
489489

490490
fn serialize_i8(self, value: i8) -> Result<String> {

tests/test.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,17 +1654,6 @@ fn test_deserialize_from_stream() {
16541654
assert_eq!(request, response);
16551655
}
16561656

1657-
#[test]
1658-
fn test_serialize_rejects_bool_keys() {
1659-
let map = treemap!(
1660-
true => 2,
1661-
false => 4,
1662-
);
1663-
1664-
let err = to_vec(&map).unwrap_err();
1665-
assert_eq!(err.to_string(), "key must be a string");
1666-
}
1667-
16681657
#[test]
16691658
fn test_serialize_rejects_adt_keys() {
16701659
let map = treemap!(
@@ -2018,6 +2007,14 @@ fn test_deny_non_finite_f64_key() {
20182007
assert!(serde_json::to_value(map).is_err());
20192008
}
20202009

2010+
#[test]
2011+
fn test_boolean_key() {
2012+
let map = treemap!(false => 0, true => 1);
2013+
let j = r#"{"false":0,"true":1}"#;
2014+
test_encode_ok(&[(&map, j)]);
2015+
test_parse_ok(vec![(j, map)]);
2016+
}
2017+
20212018
#[test]
20222019
fn test_borrowed_key() {
20232020
let map: BTreeMap<&str, ()> = from_str("{\"borrowed\":null}").unwrap();

0 commit comments

Comments
 (0)