Remove ReflectJsonSchema, functionality is provided by CustomInternalSchemaData

This commit is contained in:
Piotr Siuszko 2025-07-10 19:23:10 +02:00
parent f404446756
commit dd20a3bd34
5 changed files with 124 additions and 121 deletions

View File

@ -1871,7 +1871,7 @@ mod tests {
let mut register = atr.write();
register.register::<NestedStruct>();
register.register::<bevy_math::Vec3>();
register.register_force_as_array::<bevy_math::Vec3>();
register.registry_force_schema_to_be_array::<bevy_math::Vec3>();
}
let mut world = World::new();
world.insert_resource(atr);

View File

@ -449,7 +449,8 @@ impl SchemaType {
mod tests {
use crate::schemas::open_rpc::OpenRpcDocument;
use crate::schemas::reflect_info::ReferenceLocation;
use crate::schemas::ReflectJsonSchema;
use crate::schemas::CustomInternalSchemaData;
use crate::schemas::ExternalSchemaSource;
use super::*;
use bevy_ecs::prelude::ReflectComponent;
@ -631,7 +632,7 @@ mod tests {
{
let mut register = atr.write();
register.register::<OpenRpcDocument>();
register.register_type_data::<OpenRpcDocument, ReflectJsonSchema>();
register.register_type_data::<OpenRpcDocument, CustomInternalSchemaData>();
}
let type_registry = atr.read();
let schema = type_registry
@ -656,20 +657,16 @@ mod tests {
#[test]
fn reflect_export_with_custom_schema() {
/// Custom type for testing purposes.
#[derive(Reflect, Component)]
struct SomeType;
impl bevy_reflect::FromType<SomeType> for ReflectJsonSchema {
fn from_type() -> Self {
JsonSchemaBevyType {
ref_type: Some(TypeReferencePath::new_ref(
ReferenceLocation::Url,
"raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json",
)),
description: Some("Custom type for testing purposes.".into()),
..Default::default()
}
.into()
impl ExternalSchemaSource for SomeType {
fn get_external_schema_source() -> TypeReferencePath {
TypeReferencePath::new_ref(
ReferenceLocation::Url,
"raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json",
)
}
}
@ -677,7 +674,7 @@ mod tests {
{
let mut register = atr.write();
register.register::<SomeType>();
register.register_type_data::<SomeType, ReflectJsonSchema>();
register.register_type_data::<SomeType, CustomInternalSchemaData>();
}
let type_registry = atr.read();
let schema = type_registry

View File

@ -1,6 +1,5 @@
//! Module with schemas used for various BRP endpoints
use alloc::borrow::Cow;
use bevy_derive::Deref;
use bevy_ecs::{
reflect::{ReflectComponent, ReflectResource},
resource::Resource,
@ -13,9 +12,8 @@ use bevy_reflect::{
use core::any::TypeId;
use crate::schemas::{
json_schema::JsonSchemaBevyType,
open_rpc::OpenRpcDocument,
reflect_info::{FieldsInformation, InternalSchemaType},
reflect_info::{FieldsInformation, InternalSchemaType, TypeReferencePath},
};
pub mod json_schema;
@ -36,18 +34,17 @@ pub struct SchemaTypesMetadata {
#[reflect(Resource)]
pub struct CustomInternalSchemaData(pub InternalSchemaType);
impl CustomInternalSchemaData {
/// Creates a new `CustomInternalSchema` with a forced array type. Works for structs only.
pub fn force_array<T: GetTypeRegistration>() -> Option<Self> {
match T::get_type_registration().type_info() {
bevy_reflect::TypeInfo::Struct(struct_info) => Some(CustomInternalSchemaData(
InternalSchemaType::FieldsHolder(FieldsInformation::new(
struct_info.iter(),
reflect_info::FieldType::ForceUnnamed(struct_info.ty().id()),
)),
)),
_ => None,
}
/// Trait for external schema sources.
pub trait ExternalSchemaSource {
/// Get the external schema source.
fn get_external_schema_source() -> TypeReferencePath;
}
impl<T: Reflect + ExternalSchemaSource> FromType<T> for CustomInternalSchemaData {
fn from_type() -> Self {
Self(InternalSchemaType::ExternalSource(
T::get_external_schema_source(),
))
}
}
@ -57,60 +54,60 @@ pub(crate) trait RegisterReflectJsonSchemas {
fn register_schema_base_types(&mut self) {
#[cfg(feature = "bevy_math")]
{
self.register_force_as_array::<bevy_math::Vec2>();
self.register_force_as_array::<bevy_math::DVec2>();
self.register_force_as_array::<bevy_math::I8Vec2>();
self.register_force_as_array::<bevy_math::U8Vec2>();
self.register_force_as_array::<bevy_math::I16Vec2>();
self.register_force_as_array::<bevy_math::U16Vec2>();
self.register_force_as_array::<bevy_math::IVec2>();
self.register_force_as_array::<bevy_math::UVec2>();
self.register_force_as_array::<bevy_math::I64Vec2>();
self.register_force_as_array::<bevy_math::U64Vec2>();
self.register_force_as_array::<bevy_math::BVec2>();
self.registry_force_schema_to_be_array::<bevy_math::Vec2>();
self.registry_force_schema_to_be_array::<bevy_math::DVec2>();
self.registry_force_schema_to_be_array::<bevy_math::I8Vec2>();
self.registry_force_schema_to_be_array::<bevy_math::U8Vec2>();
self.registry_force_schema_to_be_array::<bevy_math::I16Vec2>();
self.registry_force_schema_to_be_array::<bevy_math::U16Vec2>();
self.registry_force_schema_to_be_array::<bevy_math::IVec2>();
self.registry_force_schema_to_be_array::<bevy_math::UVec2>();
self.registry_force_schema_to_be_array::<bevy_math::I64Vec2>();
self.registry_force_schema_to_be_array::<bevy_math::U64Vec2>();
self.registry_force_schema_to_be_array::<bevy_math::BVec2>();
self.register_force_as_array::<bevy_math::Vec3A>();
self.register_force_as_array::<bevy_math::Vec3>();
self.register_force_as_array::<bevy_math::DVec3>();
self.register_force_as_array::<bevy_math::I8Vec3>();
self.register_force_as_array::<bevy_math::U8Vec3>();
self.register_force_as_array::<bevy_math::I16Vec3>();
self.register_force_as_array::<bevy_math::U16Vec3>();
self.register_force_as_array::<bevy_math::IVec3>();
self.register_force_as_array::<bevy_math::UVec3>();
self.register_force_as_array::<bevy_math::I64Vec3>();
self.register_force_as_array::<bevy_math::U64Vec3>();
self.register_force_as_array::<bevy_math::BVec3>();
self.registry_force_schema_to_be_array::<bevy_math::Vec3A>();
self.registry_force_schema_to_be_array::<bevy_math::Vec3>();
self.registry_force_schema_to_be_array::<bevy_math::DVec3>();
self.registry_force_schema_to_be_array::<bevy_math::I8Vec3>();
self.registry_force_schema_to_be_array::<bevy_math::U8Vec3>();
self.registry_force_schema_to_be_array::<bevy_math::I16Vec3>();
self.registry_force_schema_to_be_array::<bevy_math::U16Vec3>();
self.registry_force_schema_to_be_array::<bevy_math::IVec3>();
self.registry_force_schema_to_be_array::<bevy_math::UVec3>();
self.registry_force_schema_to_be_array::<bevy_math::I64Vec3>();
self.registry_force_schema_to_be_array::<bevy_math::U64Vec3>();
self.registry_force_schema_to_be_array::<bevy_math::BVec3>();
self.register_force_as_array::<bevy_math::Vec4>();
self.register_force_as_array::<bevy_math::DVec4>();
self.register_force_as_array::<bevy_math::I8Vec4>();
self.register_force_as_array::<bevy_math::U8Vec4>();
self.register_force_as_array::<bevy_math::I16Vec4>();
self.register_force_as_array::<bevy_math::U16Vec4>();
self.register_force_as_array::<bevy_math::IVec4>();
self.register_force_as_array::<bevy_math::UVec4>();
self.register_force_as_array::<bevy_math::I64Vec4>();
self.register_force_as_array::<bevy_math::U64Vec4>();
self.register_force_as_array::<bevy_math::BVec4>();
self.registry_force_schema_to_be_array::<bevy_math::Vec4>();
self.registry_force_schema_to_be_array::<bevy_math::DVec4>();
self.registry_force_schema_to_be_array::<bevy_math::I8Vec4>();
self.registry_force_schema_to_be_array::<bevy_math::U8Vec4>();
self.registry_force_schema_to_be_array::<bevy_math::I16Vec4>();
self.registry_force_schema_to_be_array::<bevy_math::U16Vec4>();
self.registry_force_schema_to_be_array::<bevy_math::IVec4>();
self.registry_force_schema_to_be_array::<bevy_math::UVec4>();
self.registry_force_schema_to_be_array::<bevy_math::I64Vec4>();
self.registry_force_schema_to_be_array::<bevy_math::U64Vec4>();
self.registry_force_schema_to_be_array::<bevy_math::BVec4>();
self.register_force_as_array::<bevy_math::Quat>();
self.register_force_as_array::<bevy_math::DQuat>();
self.registry_force_schema_to_be_array::<bevy_math::Quat>();
self.registry_force_schema_to_be_array::<bevy_math::DQuat>();
self.register_force_as_array::<bevy_math::Mat2>();
self.register_force_as_array::<bevy_math::DMat2>();
self.register_force_as_array::<bevy_math::DMat3>();
self.register_force_as_array::<bevy_math::Mat3A>();
self.register_force_as_array::<bevy_math::Mat3>();
self.register_force_as_array::<bevy_math::DMat4>();
self.register_force_as_array::<bevy_math::Mat4>();
self.register_force_as_array::<bevy_math::Affine2>();
self.register_force_as_array::<bevy_math::DAffine2>();
self.register_force_as_array::<bevy_math::DAffine3>();
self.register_force_as_array::<bevy_math::Affine3A>();
self.registry_force_schema_to_be_array::<bevy_math::Mat2>();
self.registry_force_schema_to_be_array::<bevy_math::DMat2>();
self.registry_force_schema_to_be_array::<bevy_math::DMat3>();
self.registry_force_schema_to_be_array::<bevy_math::Mat3A>();
self.registry_force_schema_to_be_array::<bevy_math::Mat3>();
self.registry_force_schema_to_be_array::<bevy_math::DMat4>();
self.registry_force_schema_to_be_array::<bevy_math::Mat4>();
self.registry_force_schema_to_be_array::<bevy_math::Affine2>();
self.registry_force_schema_to_be_array::<bevy_math::DAffine2>();
self.registry_force_schema_to_be_array::<bevy_math::DAffine3>();
self.registry_force_schema_to_be_array::<bevy_math::Affine3A>();
}
self.register_type_internal::<OpenRpcDocument>();
self.register_type_data_internal::<OpenRpcDocument, ReflectJsonSchema>();
self.register_type_data_internal::<OpenRpcDocument, CustomInternalSchemaData>();
}
/// Registers a type by value.
fn register_data_type_by_value<T, D>(&mut self, data: D)
@ -125,13 +122,21 @@ pub(crate) trait RegisterReflectJsonSchemas {
where
T: Reflect + TypePath + GetTypeRegistration,
D: TypeData + FromType<T>;
fn register_force_as_array<T>(&mut self)
/// Registers a [`CustomInternalSchemaData`] data type for a type that will force to treat the type as an array during building the [`JsonSchemaBevyType`] for given type.
/// It is useful when you want to force the type to be treated as an array in the schema, for example when type has custom serialization.
fn registry_force_schema_to_be_array<T>(&mut self)
where
T: Reflect + TypePath + GetTypeRegistration,
{
let Some(data) = CustomInternalSchemaData::force_array::<T>() else {
let bevy_reflect::TypeInfo::Struct(struct_info) = T::get_type_registration().type_info()
else {
return;
};
let data =
CustomInternalSchemaData(InternalSchemaType::FieldsHolder(FieldsInformation::new(
struct_info.iter(),
reflect_info::FieldType::ForceUnnamed(struct_info.ty().id()),
)));
self.register_data_type_by_value::<T, CustomInternalSchemaData>(data);
}
}
@ -195,22 +200,6 @@ impl RegisterReflectJsonSchemas for bevy_app::App {
}
}
/// Reflect-compatible custom JSON Schema for this type
#[derive(Clone, Deref)]
pub struct ReflectJsonSchema(pub JsonSchemaBevyType);
impl From<&JsonSchemaBevyType> for ReflectJsonSchema {
fn from(schema: &JsonSchemaBevyType) -> Self {
Self(schema.clone())
}
}
impl From<JsonSchemaBevyType> for ReflectJsonSchema {
fn from(schema: JsonSchemaBevyType) -> Self {
Self(schema)
}
}
impl Default for SchemaTypesMetadata {
fn default() -> Self {
let mut data_types = Self {

View File

@ -1,15 +1,12 @@
//! Module with trimmed down `OpenRPC` document structs.
//! It tries to follow this standard: <https://spec.open-rpc.org>
use bevy_platform::collections::HashMap;
use bevy_reflect::{FromType, Reflect};
use bevy_reflect::Reflect;
use bevy_utils::default;
use serde::{Deserialize, Serialize};
use crate::{
schemas::{
reflect_info::{ReferenceLocation, TypeReferencePath},
ReflectJsonSchema,
},
schemas::reflect_info::{ReferenceLocation, TypeReferencePath},
RemoteMethods,
};
@ -29,20 +26,12 @@ pub struct OpenRpcDocument {
pub servers: Option<Vec<ServerObject>>,
}
impl FromType<OpenRpcDocument> for ReflectJsonSchema {
fn from_type() -> Self {
JsonSchemaBevyType {
ref_type: Some(TypeReferencePath::new_ref(
ReferenceLocation::Url,
"raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json",
)),
description: Some(
"Represents an `OpenRPC` document as defined by the `OpenRPC` specification."
.into(),
),
..default()
}
.into()
impl super::ExternalSchemaSource for OpenRpcDocument {
fn get_external_schema_source() -> TypeReferencePath {
TypeReferencePath::new_ref(
ReferenceLocation::Url,
"raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json",
)
}
}

View File

@ -531,7 +531,16 @@ impl TypeReferencePath {
}
impl Display for TypeReferencePath {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}{}", self.location, encode_to_uri(&self.id))
write!(
f,
"{}{}",
self.location,
if self.location == ReferenceLocation::Definitions {
encode_to_uri(&self.id)
} else {
(*self.id).to_string()
}
)
}
}
@ -929,6 +938,8 @@ pub enum InternalSchemaType {
/// Optional field data for the primitive type.
field_data: Option<SchemaFieldData>,
},
/// Variant for external source types.
ExternalSource(TypeReferencePath),
/// Variant for regular primitive types and other simple types.
Regular(TypeId),
}
@ -1100,7 +1111,7 @@ impl InternalSchemaType {
InternalSchemaType::Regular(t) => {
_ = dependencies.insert(*t);
}
InternalSchemaType::PrimitiveType { .. } => {}
InternalSchemaType::PrimitiveType { .. } | InternalSchemaType::ExternalSource(_) => {}
}
dependencies
}
@ -1137,7 +1148,9 @@ impl From<&InternalSchemaType> for Option<SchemaTypeVariant> {
InternalSchemaType::Regular(type_id) => {
Some(SchemaTypeVariant::Single((*type_id).into()))
}
InternalSchemaType::EnumHolder(_) | InternalSchemaType::Optional { generic: _ } => None,
InternalSchemaType::EnumHolder(_)
| InternalSchemaType::Optional { generic: _ }
| InternalSchemaType::ExternalSource(_) => None,
}
}
}
@ -1472,9 +1485,7 @@ impl TypeDefinitionBuilder for TypeRegistry {
let internal = InternalSchemaType::from_type_registration(type_reg, self);
let mut id: Option<TypeReferenceId> = Some(type_reg.type_info().type_path().into());
if let Some(custom_schema) = &type_reg.data::<super::ReflectJsonSchema>() {
return Some((id, custom_schema.0.clone()));
}
let range: MinMaxValues = type_id.into();
let type_path_table = type_reg.type_info().type_path_table();
let (type_path, short_path, crate_name, module_path) = (
@ -1512,6 +1523,16 @@ impl TypeDefinitionBuilder for TypeRegistry {
};
schema.schema_type = (&internal).into();
match internal {
InternalSchemaType::ExternalSource(source) => {
return Some((
None,
JsonSchemaBevyType {
description: schema.description,
ref_type: Some(source),
..Default::default()
},
));
}
InternalSchemaType::PrimitiveType {
type_id: _,
primitive: _,
@ -1641,6 +1662,13 @@ impl TypeDefinitionBuilder for TypeRegistry {
let internal = InternalSchemaType::from_type_registration(type_reg, self);
schema.schema_type = (&internal).into();
match internal {
InternalSchemaType::ExternalSource(source) => {
return Some(JsonSchemaBevyType {
description: schema.description,
ref_type: Some(source),
..Default::default()
});
}
InternalSchemaType::PrimitiveType {
type_id,
primitive: _,