When is it safe to call unwrap on the result of `serde_json::to_string`?

Let's say I have an instance of this struct:

#[derive(Debug, Serialize, Deserialize)]
pub struct Payload {
    #[serde(skip_serializing)]
    pub k1: String,
    pub k2: u32,
    pub k3: u64,
    #[serde(flatten)]
    pub rest: Value,
}

How safe is it to call serde_json::to_string(o).unwrap()? The documentation states that Serialization can fail if T's implementation of Serialize decides to fail, or if T contains a map with non-string keys. It looks to me like calling unwrap is safe here but I want to be sure? Am I overlooking something?

If you call unwrap, then your code will crash if the json is invalid. It's safe to call unwrap if such crashes are okay.

This is asking about converting to a json string, where it's a lot less clear why it might fail.

I assume most derived Serialize implementations won't fail, but there isn't anything on Using derive · Serde to promise such.

An obvious counter example is using #[serde(serialize_with)] or equivalent, but it's entirely possible there's other less visible cases...

2 Likes

If you know all cases in which serde_json::to_string() might return a Result::Err and you can prove that your code only serializes objects that will never trigger any of these conditions, you can .expect() the result with an appropriate message that clarifies the reasoning why this can never happen and, if it does, that this is a bug. E.g.:

let string = serde_json::to_string(o).expect("Serializing an o can never trigger a serialization error, because trust me. This is a bug.");

I don't know. How is serde::Serialize implemented on Value?

1 Like

Value is serde_json::Value

The Serializer for Value implementation is here: json/src/value/ser.rs at master · serde-rs/json · GitHub

Other than the documented non string (or, apparently, number) map keys, and errors forwarded from the Serialize implementation, looks like numbers being out of range when arbitrary_precision feature isn't enabled will also error?

Here's an example for your type where it would fail: Rust Playground

arrays can't be keys in json

2 Likes

My bad. I forgot to mention that the rest of the code ensures that Value will be an object.