Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/serde/mod.rs
6599 views
1
//! Serde integration for reflected types.
2
3
mod de;
4
mod ser;
5
mod type_data;
6
7
pub use de::*;
8
pub use ser::*;
9
pub use type_data::*;
10
11
#[cfg(test)]
12
mod tests {
13
use super::*;
14
use crate::{
15
type_registry::TypeRegistry, DynamicStruct, DynamicTupleStruct, FromReflect,
16
PartialReflect, Reflect, Struct,
17
};
18
use serde::de::DeserializeSeed;
19
20
#[test]
21
fn test_serialization_struct() {
22
#[derive(Debug, Reflect, PartialEq)]
23
#[reflect(PartialEq)]
24
struct TestStruct {
25
a: i32,
26
#[reflect(ignore)]
27
b: i32,
28
#[reflect(skip_serializing)]
29
c: i32,
30
#[reflect(skip_serializing)]
31
#[reflect(default = "custom_default")]
32
d: i32,
33
e: i32,
34
}
35
36
fn custom_default() -> i32 {
37
-1
38
}
39
40
let mut registry = TypeRegistry::default();
41
registry.register::<TestStruct>();
42
43
let test_struct = TestStruct {
44
a: 3,
45
b: 4,
46
c: 5,
47
d: 6,
48
e: 7,
49
};
50
51
let serializer = ReflectSerializer::new(&test_struct, &registry);
52
let serialized =
53
ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
54
55
let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap();
56
let reflect_deserializer = ReflectDeserializer::new(&registry);
57
let deserialized = reflect_deserializer.deserialize(&mut deserializer).unwrap();
58
59
let mut expected = DynamicStruct::default();
60
expected.insert("a", 3);
61
// Ignored: expected.insert("b", 0);
62
expected.insert("c", 0);
63
expected.insert("d", -1);
64
expected.insert("e", 7);
65
66
assert!(
67
expected
68
.reflect_partial_eq(deserialized.as_partial_reflect())
69
.unwrap(),
70
"Deserialization failed: expected {expected:?} found {deserialized:?}"
71
);
72
73
let expected = TestStruct {
74
a: 3,
75
b: 0,
76
c: 0,
77
d: -1,
78
e: 7,
79
};
80
let received =
81
<TestStruct as FromReflect>::from_reflect(deserialized.as_partial_reflect()).unwrap();
82
83
assert_eq!(
84
expected, received,
85
"FromReflect failed: expected {expected:?} found {received:?}"
86
);
87
}
88
89
#[test]
90
fn test_serialization_tuple_struct() {
91
#[derive(Debug, Reflect, PartialEq)]
92
#[reflect(PartialEq)]
93
struct TestStruct(
94
i32,
95
#[reflect(ignore)] i32,
96
#[reflect(skip_serializing)] i32,
97
#[reflect(skip_serializing)]
98
#[reflect(default = "custom_default")]
99
i32,
100
i32,
101
);
102
103
fn custom_default() -> i32 {
104
-1
105
}
106
107
let mut registry = TypeRegistry::default();
108
registry.register::<TestStruct>();
109
110
let test_struct = TestStruct(3, 4, 5, 6, 7);
111
112
let serializer = ReflectSerializer::new(&test_struct, &registry);
113
let serialized =
114
ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
115
116
let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap();
117
let reflect_deserializer = ReflectDeserializer::new(&registry);
118
let deserialized = reflect_deserializer.deserialize(&mut deserializer).unwrap();
119
120
let mut expected = DynamicTupleStruct::default();
121
expected.insert(3);
122
// Ignored: expected.insert(0);
123
expected.insert(0);
124
expected.insert(-1);
125
expected.insert(7);
126
127
assert!(
128
expected
129
.reflect_partial_eq(deserialized.as_partial_reflect())
130
.unwrap(),
131
"Deserialization failed: expected {expected:?} found {deserialized:?}"
132
);
133
134
let expected = TestStruct(3, 0, 0, -1, 7);
135
let received =
136
<TestStruct as FromReflect>::from_reflect(deserialized.as_partial_reflect()).unwrap();
137
138
assert_eq!(
139
expected, received,
140
"FromReflect failed: expected {expected:?} found {received:?}"
141
);
142
}
143
144
#[test]
145
#[should_panic(
146
expected = "cannot serialize dynamic value without represented type: `bevy_reflect::DynamicStruct`"
147
)]
148
fn should_not_serialize_unproxied_dynamic() {
149
let registry = TypeRegistry::default();
150
151
let mut value = DynamicStruct::default();
152
value.insert("foo", 123_u32);
153
154
let serializer = ReflectSerializer::new(&value, &registry);
155
ron::ser::to_string(&serializer).unwrap();
156
}
157
158
#[test]
159
fn should_roundtrip_proxied_dynamic() {
160
#[derive(Reflect)]
161
struct TestStruct {
162
a: i32,
163
b: i32,
164
}
165
166
let mut registry = TypeRegistry::default();
167
registry.register::<TestStruct>();
168
169
let value: DynamicStruct = TestStruct { a: 123, b: 456 }.to_dynamic_struct();
170
171
let serializer = ReflectSerializer::new(&value, &registry);
172
173
let expected = r#"{"bevy_reflect::serde::tests::TestStruct":(a:123,b:456)}"#;
174
let result = ron::ser::to_string(&serializer).unwrap();
175
assert_eq!(expected, result);
176
177
let mut deserializer = ron::de::Deserializer::from_str(&result).unwrap();
178
let reflect_deserializer = ReflectDeserializer::new(&registry);
179
180
let expected = value.to_dynamic();
181
let result = reflect_deserializer.deserialize(&mut deserializer).unwrap();
182
183
assert!(expected
184
.reflect_partial_eq(result.as_partial_reflect())
185
.unwrap());
186
}
187
188
mod type_data {
189
use super::*;
190
use crate::from_reflect::FromReflect;
191
use crate::serde::{DeserializeWithRegistry, ReflectDeserializeWithRegistry};
192
use crate::serde::{ReflectSerializeWithRegistry, SerializeWithRegistry};
193
use crate::{ReflectFromReflect, TypePath};
194
use alloc::{format, string::String, vec, vec::Vec};
195
use bevy_platform::sync::Arc;
196
use bevy_reflect_derive::reflect_trait;
197
use core::any::TypeId;
198
use core::fmt::{Debug, Formatter};
199
use serde::de::{SeqAccess, Visitor};
200
use serde::ser::SerializeSeq;
201
use serde::{Deserializer, Serialize, Serializer};
202
203
#[reflect_trait]
204
trait Enemy: Reflect + Debug {
205
#[expect(dead_code, reason = "this method is purely for testing purposes")]
206
fn hp(&self) -> u8;
207
}
208
209
// This is needed to support Arc<dyn Enemy>
210
impl TypePath for dyn Enemy {
211
fn type_path() -> &'static str {
212
"dyn bevy_reflect::serde::tests::type_data::Enemy"
213
}
214
215
fn short_type_path() -> &'static str {
216
"dyn Enemy"
217
}
218
}
219
220
#[derive(Reflect, Debug)]
221
#[reflect(Enemy)]
222
struct Skeleton(u8);
223
224
impl Enemy for Skeleton {
225
fn hp(&self) -> u8 {
226
self.0
227
}
228
}
229
230
#[derive(Reflect, Debug)]
231
#[reflect(Enemy)]
232
struct Zombie {
233
health: u8,
234
walk_speed: f32,
235
}
236
237
impl Enemy for Zombie {
238
fn hp(&self) -> u8 {
239
self.health
240
}
241
}
242
243
#[derive(Reflect, Debug)]
244
struct Level {
245
name: String,
246
enemies: EnemyList,
247
}
248
249
#[derive(Reflect, Debug)]
250
#[reflect(SerializeWithRegistry, DeserializeWithRegistry)]
251
// Note that we have to use `Arc` instead of `Box` here due to the
252
// former being the only one between the two to implement `Reflect`.
253
struct EnemyList(Vec<Arc<dyn Enemy>>);
254
255
impl SerializeWithRegistry for EnemyList {
256
fn serialize<S>(
257
&self,
258
serializer: S,
259
registry: &TypeRegistry,
260
) -> Result<S::Ok, S::Error>
261
where
262
S: Serializer,
263
{
264
let mut state = serializer.serialize_seq(Some(self.0.len()))?;
265
for enemy in &self.0 {
266
state.serialize_element(&ReflectSerializer::new(
267
(**enemy).as_partial_reflect(),
268
registry,
269
))?;
270
}
271
state.end()
272
}
273
}
274
275
impl<'de> DeserializeWithRegistry<'de> for EnemyList {
276
fn deserialize<D>(deserializer: D, registry: &TypeRegistry) -> Result<Self, D::Error>
277
where
278
D: Deserializer<'de>,
279
{
280
struct EnemyListVisitor<'a> {
281
registry: &'a TypeRegistry,
282
}
283
284
impl<'a, 'de> Visitor<'de> for EnemyListVisitor<'a> {
285
type Value = Vec<Arc<dyn Enemy>>;
286
287
fn expecting(&self, formatter: &mut Formatter) -> core::fmt::Result {
288
write!(formatter, "a list of enemies")
289
}
290
291
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
292
where
293
A: SeqAccess<'de>,
294
{
295
let mut enemies = Vec::new();
296
while let Some(enemy) =
297
seq.next_element_seed(ReflectDeserializer::new(self.registry))?
298
{
299
let registration = self
300
.registry
301
.get_with_type_path(
302
enemy.get_represented_type_info().unwrap().type_path(),
303
)
304
.unwrap();
305
306
// 1. Convert any possible dynamic values to concrete ones
307
let enemy = registration
308
.data::<ReflectFromReflect>()
309
.unwrap()
310
.from_reflect(&*enemy)
311
.unwrap();
312
313
// 2. Convert the concrete value to a boxed trait object
314
let enemy = registration
315
.data::<ReflectEnemy>()
316
.unwrap()
317
.get_boxed(enemy)
318
.unwrap();
319
320
enemies.push(enemy.into());
321
}
322
323
Ok(enemies)
324
}
325
}
326
327
deserializer
328
.deserialize_seq(EnemyListVisitor { registry })
329
.map(EnemyList)
330
}
331
}
332
333
fn create_registry() -> TypeRegistry {
334
let mut registry = TypeRegistry::default();
335
registry.register::<Level>();
336
registry.register::<EnemyList>();
337
registry.register::<Skeleton>();
338
registry.register::<Zombie>();
339
registry
340
}
341
342
fn create_arc_dyn_enemy<T: Enemy>(enemy: T) -> Arc<dyn Enemy> {
343
let arc = Arc::new(enemy);
344
345
#[cfg(not(target_has_atomic = "ptr"))]
346
#[expect(
347
unsafe_code,
348
reason = "unsized coercion is an unstable feature for non-std types"
349
)]
350
// SAFETY:
351
// - Coercion from `T` to `dyn Enemy` is valid as `T: Enemy + 'static`
352
// - `Arc::from_raw` receives a valid pointer from a previous call to `Arc::into_raw`
353
let arc = unsafe { Arc::from_raw(Arc::into_raw(arc) as *const dyn Enemy) };
354
355
arc
356
}
357
358
#[test]
359
fn should_serialize_with_serialize_with_registry() {
360
let registry = create_registry();
361
362
let level = Level {
363
name: String::from("Level 1"),
364
enemies: EnemyList(vec![
365
create_arc_dyn_enemy(Skeleton(10)),
366
create_arc_dyn_enemy(Zombie {
367
health: 20,
368
walk_speed: 0.5,
369
}),
370
]),
371
};
372
373
let serializer = ReflectSerializer::new(&level, &registry);
374
let serialized = ron::ser::to_string(&serializer).unwrap();
375
376
let expected = r#"{"bevy_reflect::serde::tests::type_data::Level":(name:"Level 1",enemies:[{"bevy_reflect::serde::tests::type_data::Skeleton":(10)},{"bevy_reflect::serde::tests::type_data::Zombie":(health:20,walk_speed:0.5)}])}"#;
377
378
assert_eq!(expected, serialized);
379
}
380
381
#[test]
382
fn should_deserialize_with_deserialize_with_registry() {
383
let registry = create_registry();
384
385
let input = r#"{"bevy_reflect::serde::tests::type_data::Level":(name:"Level 1",enemies:[{"bevy_reflect::serde::tests::type_data::Skeleton":(10)},{"bevy_reflect::serde::tests::type_data::Zombie":(health:20,walk_speed:0.5)}])}"#;
386
387
let mut deserializer = ron::de::Deserializer::from_str(input).unwrap();
388
let reflect_deserializer = ReflectDeserializer::new(&registry);
389
let value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
390
391
let output = Level::from_reflect(&*value).unwrap();
392
393
let expected = Level {
394
name: String::from("Level 1"),
395
enemies: EnemyList(vec![
396
create_arc_dyn_enemy(Skeleton(10)),
397
create_arc_dyn_enemy(Zombie {
398
health: 20,
399
walk_speed: 0.5,
400
}),
401
]),
402
};
403
404
// Poor man's comparison since we can't derive PartialEq for Arc<dyn Enemy>
405
assert_eq!(format!("{expected:?}"), format!("{output:?}",));
406
407
let unexpected = Level {
408
name: String::from("Level 1"),
409
enemies: EnemyList(vec![
410
create_arc_dyn_enemy(Skeleton(20)),
411
create_arc_dyn_enemy(Zombie {
412
health: 20,
413
walk_speed: 5.0,
414
}),
415
]),
416
};
417
418
// Poor man's comparison since we can't derive PartialEq for Arc<dyn Enemy>
419
assert_ne!(format!("{unexpected:?}"), format!("{output:?}"));
420
}
421
422
#[test]
423
fn should_serialize_single_tuple_struct_as_newtype() {
424
#[derive(Reflect, Serialize, PartialEq, Debug)]
425
struct TupleStruct(u32);
426
427
#[derive(Reflect, Serialize, PartialEq, Debug)]
428
struct TupleStructWithSkip(
429
u32,
430
#[reflect(skip_serializing)]
431
#[serde(skip)]
432
u32,
433
);
434
435
#[derive(Reflect, Serialize, PartialEq, Debug)]
436
enum Enum {
437
TupleStruct(usize),
438
NestedTupleStruct(TupleStruct),
439
NestedTupleStructWithSkip(TupleStructWithSkip),
440
}
441
442
let mut registry = TypeRegistry::default();
443
registry.register::<TupleStruct>();
444
registry.register::<TupleStructWithSkip>();
445
registry.register::<Enum>();
446
447
let tuple_struct = TupleStruct(1);
448
let tuple_struct_with_skip = TupleStructWithSkip(2, 3);
449
let tuple_struct_enum = Enum::TupleStruct(4);
450
let nested_tuple_struct = Enum::NestedTupleStruct(TupleStruct(5));
451
let nested_tuple_struct_with_skip =
452
Enum::NestedTupleStructWithSkip(TupleStructWithSkip(6, 7));
453
454
fn assert_serialize<T: Reflect + FromReflect + Serialize + PartialEq + Debug>(
455
value: &T,
456
registry: &TypeRegistry,
457
) {
458
let serializer = TypedReflectSerializer::new(value, registry);
459
let reflect_serialize = serde_json::to_string(&serializer).unwrap();
460
let serde_serialize = serde_json::to_string(value).unwrap();
461
assert_eq!(reflect_serialize, serde_serialize);
462
463
let registration = registry.get(TypeId::of::<T>()).unwrap();
464
let reflect_deserializer = TypedReflectDeserializer::new(registration, registry);
465
466
let mut deserializer = serde_json::Deserializer::from_str(&serde_serialize);
467
let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
468
let _ = T::from_reflect(&*reflect_value).unwrap();
469
}
470
471
assert_serialize(&tuple_struct, &registry);
472
assert_serialize(&tuple_struct_with_skip, &registry);
473
assert_serialize(&tuple_struct_enum, &registry);
474
assert_serialize(&nested_tuple_struct, &registry);
475
assert_serialize(&nested_tuple_struct_with_skip, &registry);
476
}
477
}
478
}
479
480