Skip to content

Commit

Permalink
Handle arbitrary number precision with serde correctly.
Browse files Browse the repository at this point in the history
  • Loading branch information
timothee-haudebourg committed Feb 15, 2024
1 parent 9e087d1 commit 54093a1
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "json-syntax"
version = "0.11.4"
version = "0.11.5"
edition = "2021"
authors = ["Timothée Haudebourg <author@haudebourg.net>"]
description = "Strict JSON parsing and mapping library"
Expand Down
68 changes: 64 additions & 4 deletions src/serde/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,73 @@ impl<'de> Deserialize<'de> for Value {
where
V: MapAccess<'de>,
{
let mut object = Object::new();
const NUMBER_TOKEN: &str = "$serde_json::private::Number";

while let Some((key, value)) = visitor.next_entry()? {
object.insert(key, value);
enum MapTag {
Number,
None(Key)
}

Ok(Value::Object(object))
impl<'de> Deserialize<'de> for MapTag {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>
{
struct Visitor;

impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = MapTag;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string key")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error
{
if v == NUMBER_TOKEN {
Ok(MapTag::Number)
} else {
Ok(MapTag::None(v.into()))
}
}

fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error
{
if v == NUMBER_TOKEN {
Ok(MapTag::Number)
} else {
Ok(MapTag::None(v.into()))
}
}
}

deserializer.deserialize_string(Visitor)
}
}

match visitor.next_key()? {
Some(MapTag::Number) => {
let value = visitor.next_value()?;
Ok(Value::Number(value))
}
Some(MapTag::None(key)) => {
let mut object = Object::new();

object.insert(key, visitor.next_value()?);
while let Some((key, value)) = visitor.next_entry()? {
object.insert(key, value);
}

Ok(Value::Object(object))
}
None => {
Ok(Value::Object(Object::new()))
}
}
}
}

Expand Down

0 comments on commit 54093a1

Please sign in to comment.