Skip to content

Commit 6fcf811

Browse files
committed
implement fix for broken sbor json model
1 parent 2ed7aff commit 6fcf811

File tree

2 files changed

+97
-1
lines changed

2 files changed

+97
-1
lines changed

crates/sbor-json/src/scrypto/programmatic/value.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,10 @@ pub enum ProgrammaticScryptoValue {
7676
},
7777
Enum {
7878
#[serde(rename = "variant_id")]
79-
#[serde_as(as = "serde_with::DisplayFromStr")]
79+
// TODO: Revert back once the gateway is past the transition phase.
80+
// #[serde_as(as = "serde_with::DisplayFromStr")]
81+
#[serde(serialize_with = "serialize_enum_discriminator")]
82+
#[serde(deserialize_with = "deserialize_enum_discriminator")]
8083
discriminator: u8,
8184
fields: Vec<ProgrammaticScryptoValue>,
8285
},
@@ -418,3 +421,30 @@ impl ProgrammaticScryptoValue {
418421
}
419422
}
420423
}
424+
425+
fn serialize_enum_discriminator<S>(
426+
value: &u8,
427+
serializer: S,
428+
) -> Result<S::Ok, S::Error>
429+
where
430+
S: serde::ser::Serializer,
431+
{
432+
serializer.serialize_str(&value.to_string())
433+
}
434+
435+
fn deserialize_enum_discriminator<'de, D>(
436+
deserializer: D,
437+
) -> Result<u8, D::Error>
438+
where
439+
D: serde::de::Deserializer<'de>,
440+
{
441+
match serde_json::Value::deserialize(deserializer)? {
442+
serde_json::Value::Number(number) => number
443+
.as_u64()
444+
.and_then(|value| u8::try_from(value).ok())
445+
.ok_or(serde::de::Error::custom("Not a valid number")),
446+
serde_json::Value::String(string) => u8::from_str(&string)
447+
.map_err(|_| serde::de::Error::custom("Not a valid number")),
448+
_ => Err(serde::de::Error::custom("Neither a number nor a string")),
449+
}
450+
}

crates/sbor-json/tests/programmatic_scrypto_sbor.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,72 @@ pub fn value_with_two_address_of_the_differing_networks_has_a_network_mismatch()
199199
assert!(contains_network_mismatch)
200200
}
201201

202+
#[test]
203+
pub fn enum_with_string_variant_id_can_be_deserialized() {
204+
// Arrange
205+
let value = r#"
206+
{
207+
"kind": "Enum",
208+
"variant_id": "10",
209+
"fields": []
210+
}
211+
"#;
212+
213+
// Act
214+
let value = serde_json::from_str::<ProgrammaticScryptoValue>(&value);
215+
216+
// Assert
217+
assert!(matches!(
218+
value,
219+
Ok(ProgrammaticScryptoValue::Enum {
220+
discriminator: 10,
221+
fields,
222+
}) if fields.is_empty()
223+
))
224+
}
225+
226+
#[test]
227+
pub fn enum_with_numeric_variant_id_can_be_deserialized() {
228+
// Arrange
229+
let value = r#"
230+
{
231+
"kind": "Enum",
232+
"variant_id": 10,
233+
"fields": []
234+
}
235+
"#;
236+
237+
// Act
238+
let value = serde_json::from_str::<ProgrammaticScryptoValue>(&value);
239+
240+
// Assert
241+
assert!(matches!(
242+
value,
243+
Ok(ProgrammaticScryptoValue::Enum {
244+
discriminator: 10,
245+
fields,
246+
}) if fields.is_empty()
247+
))
248+
}
249+
250+
#[test]
251+
pub fn enum_is_serialized_with_string_variant_id() {
252+
// Arrange
253+
let value = ProgrammaticScryptoValue::Enum {
254+
discriminator: 10,
255+
fields: vec![],
256+
};
257+
258+
// Act
259+
let value = serde_json::to_value(&value);
260+
261+
// Assert
262+
assert_eq!(
263+
value.unwrap().get("variant_id").unwrap().as_str().unwrap(),
264+
"10"
265+
)
266+
}
267+
202268
/// Tests that the programmatic JSON representation from the
203269
/// radixdlt/radixdlt-scrypto repo and the one in this repo match.
204270
pub fn programmatic_json_representations_match<T>(object: &T)

0 commit comments

Comments
 (0)