How can I deserialize the following malformed JSON using Rust's serde:
{
"value": True
}
Using this answer, I tried the following solution:
#[macro_use]
extern crate serde_derive; // 1.0.66
extern crate serde; // 1.0.66
extern crate serde_json; // 1.0.21
use serde::de;
use std::fmt;
#[derive(Debug, PartialEq, Deserialize)]
pub struct Foo {
#[serde(deserialize_with = "deserialize_capitalized_bool")]
pub bar: bool,
}
fn deserialize_capitalized_bool<'de, D>(
deserializer: D,
) -> Result<bool, D::Error>
where
D: de::Deserializer<'de>,
{
struct CapitalizedBoolVisitor;
impl<'de> de::Visitor<'de> for CapitalizedBoolVisitor {
type Value = bool;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a True or False string")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: de::Error,
{
if v == &['T' as u8, 'r' as u8, 'e' as u8] {
Ok(true)
} else if v
== &['F' as u8, 'a' as u8, 'l' as u8, 's' as u8, 'e' as u8]
{
Ok(false)
} else {
unimplemented!();
}
}
}
deserializer.deserialize_any(CapitalizedBoolVisitor)
}
fn main() {
let json = r#"{
"bar": True
}"#;
let foo: Foo = serde_json::from_str(json).unwrap();
let expected = Foo {
bar: true
};
assert_eq!(foo, expected);
}
runnable on the playground
The problem, as far as I can tell, is that the input is not recognized as any correct type, so none of the visitor APIs work here.
UPDATE (2020-02-05):
Apparently this is not possible to solve with serde_json
(one way would be to use a custom data format or to fork serde_json
to add this functionality, as serde_json
does not deal with invalid input, see the maintainer's answer).
A hacky solution, for anyone else having similar issues, is to replace the True
and False
instances in the raw response string to true
and false
. This is definitely not perfect, since if a string contains True
or False
, those would be replaced also, but it is perhaps an acceptable solution for specific use cases.
The Hive JSON SerDe is commonly used to process JSON data like events. These events are represented as single-line strings of JSON-encoded text separated by a new line. The Hive JSON SerDe does not allow duplicate keys in map or struct key names.
Serde is a framework for serializing and deserializing Rust data structures efficiently and generically. The Serde ecosystem consists of data structures that know how to serialize and deserialize themselves along with data formats that know how to serialize and deserialize other things.
In general you can only deserialize input with a particular library if the input is in the data format that the library is for.
So for examples, if your input is not JSON, CBOR, MessagePack then you can't use serde_json, serde_cbor, or serde_messagepack to deserialize it.
The input you show appears to be YAML so you could try serde_yaml.
fn main() {
let input = r#" {
"value": True
} "#;
println!("{:#?}", serde_yaml::from_str::<serde_yaml::Value>(input).unwrap());
}
In other words the fact that data is invalid JSON tells you what library not to use — serde_json. To find the right library it's more useful to find a format that the data is valid in.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With