|
| 1 | +//! Illustrates how "reflection" serialization works in Bevy. |
| 2 | +//! |
| 3 | +//! Deriving `Reflect` will also register `SerializationData`, |
| 4 | +//! which powers reflect (de)serialization. |
| 5 | +//! Serializing reflected data *does not* require deriving serde's |
| 6 | +//! Serialize and Deserialize implementations. |
| 7 | +
|
| 8 | +use bevy::{ |
| 9 | + prelude::*, |
| 10 | + reflect::serde::{ReflectDeserializer, ReflectSerializer}, |
| 11 | +}; |
| 12 | +use serde::de::DeserializeSeed; |
| 13 | + |
| 14 | +fn main() { |
| 15 | + App::new() |
| 16 | + .add_plugins(DefaultPlugins) |
| 17 | + .add_systems(Startup, (deserialize, serialize).chain()) |
| 18 | + .run(); |
| 19 | +} |
| 20 | + |
| 21 | +/// Deriving `Reflect` includes reflecting `SerializationData` |
| 22 | +#[derive(Reflect)] |
| 23 | +pub struct Player { |
| 24 | + name: String, |
| 25 | + health: u32, |
| 26 | +} |
| 27 | + |
| 28 | +const PLAYER_JSON: &str = r#"{ |
| 29 | + "serialization::Player": { |
| 30 | + "name": "BevyPlayerOne", |
| 31 | + "health": 50 |
| 32 | + } |
| 33 | +}"#; |
| 34 | + |
| 35 | +fn deserialize(type_registry: Res<AppTypeRegistry>) { |
| 36 | + let type_registry = type_registry.read(); |
| 37 | + |
| 38 | + // a serde_json::Value that might have come from an API |
| 39 | + let value: serde_json::Value = serde_json::from_str(PLAYER_JSON).unwrap(); |
| 40 | + |
| 41 | + // alternatively, `TypedReflectDeserializer` can be used if the type |
| 42 | + // is known. |
| 43 | + let deserializer = ReflectDeserializer::new(&type_registry); |
| 44 | + // deserialize |
| 45 | + let reflect_value = deserializer.deserialize(value).unwrap(); |
| 46 | + // If Player implemented additional functionality, like Component, |
| 47 | + // this reflect_value could be used with commands.insert_reflect |
| 48 | + info!(?reflect_value); |
| 49 | + |
| 50 | + // `FromReflect` and `ReflectFromReflect` can yield a concrete value. |
| 51 | + let type_id = reflect_value.get_represented_type_info().unwrap().type_id(); |
| 52 | + let reflect_from_reflect = type_registry |
| 53 | + .get_type_data::<ReflectFromReflect>(type_id) |
| 54 | + .unwrap(); |
| 55 | + let player: Box<dyn Reflect> = reflect_from_reflect |
| 56 | + .from_reflect(reflect_value.as_partial_reflect()) |
| 57 | + .unwrap(); |
| 58 | + info!(?player); |
| 59 | +} |
| 60 | + |
| 61 | +fn serialize(type_registry: Res<AppTypeRegistry>) { |
| 62 | + let type_registry = type_registry.read(); |
| 63 | + |
| 64 | + // a concrete value |
| 65 | + let value = Player { |
| 66 | + name: "BevyPlayerSerialize".to_string(), |
| 67 | + health: 80, |
| 68 | + }; |
| 69 | + |
| 70 | + // By default, all derived `Reflect` types can be serialized using serde. No need to derive |
| 71 | + // Serialize! |
| 72 | + let serializer = ReflectSerializer::new(&value, &type_registry); |
| 73 | + let json = serde_json::to_string(&serializer).unwrap(); |
| 74 | + info!(?json); |
| 75 | +} |
0 commit comments