client-api: Fix unsetting avatar url when compat is enabled

This commit is contained in:
132ikl 2021-04-24 15:47:17 -04:00 committed by GitHub
parent ba642674af
commit 190376bf0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 68 additions and 3 deletions

View File

@ -5,6 +5,7 @@ Bug fixes:
* Fix deserialization of `r0::room::get_room_event::Response` * Fix deserialization of `r0::room::get_room_event::Response`
* More missing fields in `r0::sync::sync_events::Response` can be deserialized * More missing fields in `r0::sync::sync_events::Response` can be deserialized
* Fix `get_tags::Response` serialization * Fix `get_tags::Response` serialization
* Fix unsetting avatar URL when `compat` feature is enabled
Breaking changes: Breaking changes:

View File

@ -24,10 +24,17 @@ ruma_api! {
/// ///
/// If you activate the `compat` feature, this field being an empty string in JSON will give /// If you activate the `compat` feature, this field being an empty string in JSON will give
/// you `None` here. /// you `None` here.
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr( #[cfg_attr(
feature = "compat", feature = "compat",
serde(default, deserialize_with = "ruma_serde::empty_string_as_none") serde(
default,
deserialize_with = "ruma_serde::empty_string_as_none",
serialize_with = "ruma_serde::none_as_empty_string"
)
)]
#[cfg_attr(
not(feature = "compat"),
serde(skip_serializing_if = "Option::is_none")
)] )]
pub avatar_url: Option<&'a MxcUri>, pub avatar_url: Option<&'a MxcUri>,
} }

View File

@ -4,6 +4,10 @@ Breaking changes:
* Remove the `empty` module from the public API * Remove the `empty` module from the public API
Improvements:
* Add serialization decorator `none_as_empty_string` to serialize `None`s as empty strings
# 0.3.1 # 0.3.1
Bug fixes: Bug fixes:

View File

@ -28,6 +28,7 @@ pub use empty::vec_as_map_of_empty;
pub use raw::Raw; pub use raw::Raw;
pub use strings::{ pub use strings::{
btreemap_int_or_string_to_int_values, empty_string_as_none, int_or_string_to_int, btreemap_int_or_string_to_int_values, empty_string_as_none, int_or_string_to_int,
none_as_empty_string,
}; };
/// Check whether a value is equal to its default value. /// Check whether a value is equal to its default value.

View File

@ -3,7 +3,8 @@ use std::{collections::BTreeMap, convert::TryInto, fmt, marker::PhantomData};
use js_int::Int; use js_int::Int;
use serde::{ use serde::{
de::{self, Deserializer, IntoDeserializer as _, MapAccess, Visitor}, de::{self, Deserializer, IntoDeserializer as _, MapAccess, Visitor},
Deserialize, ser::Serializer,
Deserialize, Serialize,
}; };
/// Serde deserialization decorator to map empty Strings to None, /// Serde deserialization decorator to map empty Strings to None,
@ -30,6 +31,24 @@ where
} }
} }
/// Serde serializiation decorator to map None to an empty String,
/// and forward Somes to the Serialize implemention for T.
///
/// To be used like this:
/// `#[serde(serialize_with = "empty_string_as_none")]`
pub fn none_as_empty_string<T: Serialize, S>(
value: &Option<T>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match value {
Some(x) => x.serialize(serializer),
None => serializer.serialize_str(""),
}
}
/// Take either an integer number or a string and deserialize to an integer number. /// Take either an integer number or a string and deserialize to an integer number.
/// ///
/// To be used like this: /// To be used like this:

View File

@ -0,0 +1,33 @@
use serde::{Deserialize, Serialize};
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct StringStruct {
#[serde(
deserialize_with = "ruma_serde::empty_string_as_none",
serialize_with = "ruma_serde::none_as_empty_string"
)]
x: Option<String>,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct NoneStruct {
#[serde(skip_serializing_if = "Option::is_none")]
x: Option<String>,
}
#[test]
fn empty_se() {
let string = StringStruct { x: None };
let none = NoneStruct { x: None };
assert_eq!(to_json_value(string).unwrap(), json!({"x": ""}));
assert_eq!(to_json_value(none).unwrap(), json!({}));
}
#[test]
fn empty_de() {
let string = StringStruct { x: None };
let none = NoneStruct { x: None };
assert_eq!(from_json_value::<StringStruct>(json!({"x": ""})).unwrap(), string);
assert_eq!(from_json_value::<NoneStruct>(json!({})).unwrap(), none);
}