Use TypedReflectDeserializer to deserialize raw JSON into a reflection box.
Use T::from_reflect to get a T out of the box.
Re-serialize T directly to JSON.
Expect the reserialized JSON to equal the starting JSON.
What went wrong
The TypedReflectDeserializer expects unit structs to be JSON arrays. However, JSON serializes unit structs to null. If you try to use null in the original raw JSON, then you get Error("invalid type: null, expected reflected struct value", ...).
Additional information
Minimum reproducible:
bevy = { version = "0.14", default-features = true, features = ["serialize"] }
serde = { version = "1.0" }
serde_json = { version = "1.0", features = ["preserve_order"] }
use std::str::FromStr;
use std::fmt::Debug;
use bevy::{prelude::*, reflect::serde::TypedReflectDeserializer};
use serde::de::DeserializeSeed;
use serde::{Deserialize, Serialize};
#[derive(Reflect, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct UnitStruct;
fn test_equivalence<T>(w: &World, json_raw: &str, val: T)
where
T: Serialize + for<'de> Deserialize<'de> + Debug + Reflect + FromReflect + PartialEq
{
// Json raw to json value
let json_val = serde_json::Value::from_str(json_raw).unwrap();
// Json value to reflect
let type_registry = w.resource::<AppTypeRegistry>().read();
let registration = type_registry.get(std::any::TypeId::of::<T>()).unwrap();
let deserializer = TypedReflectDeserializer::new(registration, &type_registry);
let reflected = deserializer.deserialize(json_val.clone()).unwrap();
// Reflect to val
let extracted = T::from_reflect(reflected.as_reflect()).unwrap();
assert_eq!(val, extracted);
// Val to json value
let json_val_deser = serde_json::to_value(&val).unwrap();
assert_eq!(json_val, json_val_deser);
}
#[test]
fn bug()
{
let mut app = App::new();
app.register_type::<UnitStruct>();
test_equivalence(app.world(), "[]", UnitStruct);
}
Looks like we're not using the unit_struct methods on the serializer/deserializer. We can probably do that pretty easy with a simple field length check (being sure to exclude skip_serializing fields).
Bevy version
0.14.2
What you did
TypedReflectDeserializer
to deserialize raw JSON into a reflection box.T::from_reflect
to get aT
out of the box.T
directly to JSON.What went wrong
The
TypedReflectDeserializer
expects unit structs to be JSON arrays. However, JSON serializes unit structs tonull
. If you try to usenull
in the original raw JSON, then you getError("invalid type: null, expected reflected struct value", ...)
.Additional information
Minimum reproducible: