Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support MapKeySerializer::serialize_some #1030

Merged
merged 1 commit into from
Jun 24, 2023

Conversation

LPGhatguy
Copy link
Contributor

This PR updates MapKeySerializer::serialize_some to match Serializer::serialize_some.

Currently, all calls to serialize_some are rejected with the key_must_be_a_string error that many other variants use. Because there is no distinction between Some(T) and T in JSON, I think that serializing the underlying type directly is a better behavior for this function.

I think this change is useful for serializing types that have internal nullability. In a project I am working on, there is a bitpattern in a type I am serializing that I would like serialize as null. To behave correctly with as many serializers as I can, I use serialize_some and serialize_none. When the type is used as a key, this causes serde_json to panic, even if the value is normally fine as a key.

One argument against this change is that it creates a new footgun. Users may serialize a type like HashMap<Option<String>, T> with keys that are all Some(...), and then be surprised when the type fails to serialize with a key that is None. Currently, I think that any types that are valid map keys are always valid map keys, which is desirable.

I'm hoping to get feedback by opening this PR to figure out if this is the right direction... or not!

Copy link
Member

@dtolnay dtolnay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks — this seems fine to me.

Deserializing Map<Option<String>, T> is already permitted.

serde_json::from_str::<BTreeMap<Option<String>, ()>>(r#"{"...":null}"#).unwrap();

json/src/de.rs

Lines 2170 to 2176 in ba29a89

fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
where
V: de::Visitor<'de>,
{
// Map keys cannot be null.
visitor.visit_some(self)
}

When the type is used as a key, this causes serde_json to panic, even if the value is normally fine as a key.

Serde_json does not panic in this situation. Most likely serde_json returned an error and that got turned into a panic by something else in your project.

Users may serialize a type like HashMap<Option<String>, T> with keys that are all Some(...), and then be surprised when the type fails to serialize with a key that is None.

This is not concerning to me. As a general principle, serde operates in terms of values, not types. Being able to serialize or deserialize one particular value of a type does not convey a guarantee that you can serialize or deserialize other values of the same Rust type. For example, on all existing serde_json versions, you can serialize Map<Option<String>, T> already (as long as the map is empty). It is not meaningful to consider whether the "type" itself is supported by serde.

@dtolnay dtolnay merged commit 1153052 into serde-rs:master Jun 24, 2023
@LPGhatguy LPGhatguy deleted the map-key-serialize-some branch June 24, 2023 04:57
@LPGhatguy
Copy link
Contributor Author

Thank you for the quick response and turnaround!

Serde_json does not panic in this situation. Most likely serde_json returned an error and that got turned into a panic by something else in your project.

Whoops, my bad! I'm not sure why I took the shortcut from "error" to "panic" here. 😅

This is not concerning to me. As a general principle, serde operates in terms of values, not types. Being able to serialize or deserialize one particular value of a type does not convey a guarantee that you can serialize or deserialize other values of the same Rust type. For example, on all existing serde_json versions, you can serialize Map<Option, T> already (as long as the map is empty). It is not meaningful to consider whether the "type" itself is supported by serde.

This makes a lot of sense. Already being able to deserialize the value, and the empty map already working anyways are great examples.

crapStone added a commit to Calciumdibromid/CaBr2 that referenced this pull request Jun 29, 2023
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [serde_json](https://github.com/serde-rs/json) | dependencies | patch | `1.0.96` -> `1.0.99` |

---

### Release Notes

<details>
<summary>serde-rs/json (serde_json)</summary>

### [`v1.0.99`](https://github.com/serde-rs/json/releases/tag/v1.0.99)

[Compare Source](serde-rs/json@v1.0.98...v1.0.99)

-   Support serializing serde's **option** type in a map key ([#&#8203;1030](serde-rs/json#1030), thanks [@&#8203;LPGhatguy](https://github.com/LPGhatguy))

### [`v1.0.98`](https://github.com/serde-rs/json/releases/tag/v1.0.98)

[Compare Source](serde-rs/json@v1.0.97...v1.0.98)

-   Update indexmap dependency used by "preserve_order" feature to version 2

### [`v1.0.97`](https://github.com/serde-rs/json/releases/tag/v1.0.97)

[Compare Source](serde-rs/json@v1.0.96...v1.0.97)

-   Add `io_error_kind()` method to serde_json::Error: `fn io_error_kind(&self) -> Option<std::io::ErrorKind>` ([#&#8203;1026](serde-rs/json#1026))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNS4xMTguMCIsInVwZGF0ZWRJblZlciI6IjM1LjE0MC4zIiwidGFyZ2V0QnJhbmNoIjoiZGV2ZWxvcCJ9-->

Co-authored-by: cabr2-bot <cabr2.help@gmail.com>
Co-authored-by: crapStone <crapstone01@gmail.com>
Reviewed-on: https://codeberg.org/Calciumdibromid/CaBr2/pulls/1941
Reviewed-by: crapStone <crapstone01@gmail.com>
Co-authored-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org>
Co-committed-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants