public ComponentVisitor(GameObject gameObject, UnsafeValueView view, List <DeserializationEvent> events, SerializationMetadata metadata) : base(metadata) { SetView(view); SetEvents(events); m_CustomTypeConstructor = new ComponentTypeConstructor(gameObject, GenericTypeConstructor, metadata); }
static bool TryDeserializeAdapter <TValue>(IJsonAdapter adapter, UnsafeValueView view, ref TValue value, List <DeserializationEvent> events) { if (adapter is IJsonAdapter <TValue> typed) { try { value = typed.Deserialize(view.AsSafe()); } catch (Exception e) { events.Add(new DeserializationEvent(EventType.Exception, e)); } return(true); } if (adapter is Adapters.Contravariant.IJsonAdapter <TValue> typedContravariant) { try { // @TODO Type checking on return value. value = (TValue)typedContravariant.Deserialize(view.AsSafe()); } catch (Exception e) { events.Add(new DeserializationEvent(EventType.Exception, e)); } return(true); } return(false); }
internal void ReadValueWithAdapters <TValue>(ref TValue value, UnsafeValueView view, JsonAdapterCollection.Enumerator adapters, bool isRoot = false) { while (adapters.MoveNext()) { switch (adapters.Current) { case IJsonAdapter <TValue> typed: try { value = typed.Deserialize(new JsonDeserializationContext <TValue>(this, adapters, view, isRoot)); } catch (Exception e) { m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, e)); } return; case Adapters.Contravariant.IJsonAdapter <TValue> typedContravariant: try { // NOTE: Boxing value = (TValue)typedContravariant.Deserialize((IJsonDeserializationContext) new JsonDeserializationContext <TValue>(this, adapters, view, isRoot)); } catch (Exception e) { m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, e)); } return; } } ReadValueWithoutAdapters(ref value, view, isRoot); }
internal JsonDeserializationContext(JsonPropertyReader visitor, JsonAdapterCollection.Enumerator adapters, UnsafeValueView view, bool isRoot) { m_Visitor = visitor; m_Adapters = adapters; m_View = view; m_IsRoot = isRoot; }
public SceneVisitor(Transform sceneRoot, UnsafeValueView view, List <DeserializationEvent> events, JsonSerializationParameters parameters, SerializationMetadata metadata) : base(metadata) { SetView(view); SetEvents(events); m_Events = events; m_SceneRoot = sceneRoot; m_Parameters = parameters; }
public GameObjectVisitor(UnsafeValueView view, List <DeserializationEvent> events, SerializationMetadata metadata, Transform parent, GameObjectContainer prefabRoot, JsonSerializationParameters parameters) : base(metadata) { SetView(view); SetEvents(events); m_Events = events; m_Parameters = parameters; m_Parent = parent; m_PrefabRoot = prefabRoot; }
MissingComponent CreateMissingComponent(UnsafeValueView view) { var missingBehaviour = m_GameObject.AddComponent <MissingComponent>(); var value = new JsonObject(); var visitor = new JsonSceneReader(m_SerializationMetadata); visitor.SetView(view); PropertyContainer.Visit(ref value, visitor); missingBehaviour.JsonString = JsonSerialization.ToJson(value); return(missingBehaviour); }
internal void ReadValue <TValue>(ref TValue value, UnsafeValueView view, bool isRoot = false) { var runAdapters = !(isRoot && m_DisableRootAdapters); // Special check so we have higher perf for primitives. if (runAdapters && !RuntimeTypeInfoCache <TValue> .IsPrimitiveOrString) { ReadValueWithAdapters(ref value, view, m_Adapters.GetEnumerator(), isRoot); } else { ReadValueWithoutAdapters(ref value, view, isRoot); } }
public bool TryDeserialize <TValue>(UnsafeValueView view, ref TValue value, List <DeserializationEvent> events) { if (null != UserDefined && UserDefined.Count > 0) { foreach (var adapter in UserDefined) { if (TryDeserializeAdapter(adapter, view, ref value, events)) { return(true); } } } if (null != Global && Global.Count > 0) { foreach (var adapter in Global) { if (TryDeserializeAdapter(adapter, view, ref value, events)) { return(true); } } } if (TryDeserializeAdapter(InternalAdapter, view, ref value, events)) { return(true); } #if UNITY_EDITOR if (TryDeserializeLazyLoadReference(view.AsSafe(), ref value, events)) { return(true); } #endif return(false); }
internal void ReadValueWithoutAdapters <TValue>(ref TValue value, UnsafeValueView view, bool isRoot = false) { #if UNITY_EDITOR if (RuntimeTypeInfoCache <TValue> .IsLazyLoadReference && view.Type == TokenType.String) { var json = view.AsStringView().ToString(); if (json == s_EmptyGlobalObjectId) // Workaround issue where GlobalObjectId.TryParse returns false for empty GlobalObjectId { return; } if (UnityEditor.GlobalObjectId.TryParse(json, out var id)) { var instanceID = UnityEditor.GlobalObjectId.GlobalObjectIdentifierToInstanceIDSlow(id); PropertyContainer.SetValue(ref value, "m_InstanceID", instanceID); return; } m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Error, $"An error occured while deserializing asset reference Value=[{json}].")); return; } #endif switch (view.Type) { case TokenType.String: { var v = view.AsStringView().ToString(); TypeConversion.TryConvert(ref v, out value); break; } case TokenType.Primitive: { var p = view.AsPrimitiveView(); if (p.IsIntegral()) { if (p.IsSigned()) { var v = p.AsInt64(); TypeConversion.TryConvert(ref v, out value); } else { var v = p.AsUInt64(); TypeConversion.TryConvert(ref v, out value); } } else if (p.IsDecimal() || p.IsInfinity() || p.IsNaN()) { var v = p.AsFloat(); TypeConversion.TryConvert(ref v, out value); } else if (p.IsBoolean()) { var v = p.AsBoolean(); TypeConversion.TryConvert(ref v, out value); } else if (p.IsNull()) { value = default; } break; } default: { var metadata = view.Type == TokenType.Object ? GetSerializedContainerMetadata(view.AsObjectView()) : default; m_SerializedTypeProvider.View = view; m_SerializedTypeProvider.SerializedType = isRoot ? m_SerializedType : null; if (RuntimeTypeInfoCache <TValue> .IsNullable) { m_SerializedTypeProvider.SerializedType = Nullable.GetUnderlyingType(typeof(TValue)); } if (metadata.IsSerializedReference) { if (null == m_SerializedReferences) { m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, new Exception("Deserialization encountered a serialized object reference while running with DisableSerializedReferences."))); return; } value = (TValue)m_SerializedReferences.GetDeserializedReference(metadata.SerializedId); return; } try { DefaultTypeConstruction.Construct(ref value, m_SerializedTypeProvider); } catch (ArgumentException e) { m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, new ArgumentException(e.Message))); return; } if (metadata.HasSerializedId) { // This call is harmless to skip if we don't have serialized references. m_SerializedReferences?.AddDeserializedReference(metadata.SerializedId, value); } using (new SerializedContainerMetadataScope(this, metadata)) using (new UnsafeViewScope(this, view)) { if (RuntimeTypeInfoCache <TValue> .IsNullable) { // Unpack Nullable<T> as T var underlyingType = Nullable.GetUnderlyingType(typeof(TValue)); var underlyingValue = System.Convert.ChangeType(value, underlyingType); if (!PropertyContainer.TryAccept(this, ref underlyingValue, out var errorCode)) { switch (errorCode) { case VisitErrorCode.NullContainer: throw new ArgumentNullException(nameof(value)); case VisitErrorCode.InvalidContainerType: throw new InvalidContainerTypeException(value.GetType()); case VisitErrorCode.MissingPropertyBag: throw new MissingPropertyBagException(value.GetType()); default: throw new Exception($"Unexpected {nameof(VisitErrorCode)}=[{errorCode}]"); } } // Repack the T as Nullable<T> value = (TValue)underlyingValue; } else { if (!PropertyContainer.TryAccept(this, ref value, out var errorCode)) { switch (errorCode) { case VisitErrorCode.NullContainer: throw new ArgumentNullException(nameof(value)); case VisitErrorCode.InvalidContainerType: throw new InvalidContainerTypeException(value.GetType()); case VisitErrorCode.MissingPropertyBag: throw new MissingPropertyBagException(value.GetType()); default: throw new Exception($"Unexpected {nameof(VisitErrorCode)}=[{errorCode}]"); } } } } break; } } }
internal UnsafeViewScope CreateViewScope(UnsafeValueView view) => new UnsafeViewScope(this, view);
public void SetView(UnsafeValueView view) => m_View = view;
public UnsafeViewScope(JsonPropertyReader visitor, UnsafeValueView view) { m_View = visitor.m_View; m_Visitor = visitor; m_Visitor.m_View = view; }
void ReadValue <TValue>(ref TValue value, UnsafeValueView view, bool isRoot = false) { var runAdapters = !(isRoot && m_DisableRootAdapters); // Special check so we have higher perf for primitives. if (runAdapters && !RuntimeTypeInfoCache <TValue> .IsPrimitiveOrString) { if (m_Adapters.TryDeserialize(view, ref value, m_SerializedTypeProvider.Events)) { return; } } switch (view.Type) { case TokenType.String: { TypeConversion.TryConvert(view.AsStringView().ToString(), out value); break; } case TokenType.Primitive: { var p = view.AsPrimitiveView(); if (p.IsIntegral()) { if (p.IsSigned()) { TypeConversion.TryConvert(p.AsInt64(), out value); } else { TypeConversion.TryConvert(p.AsUInt64(), out value); } } else if (p.IsDecimal() || p.IsInfinity() || p.IsNaN()) { TypeConversion.TryConvert(p.AsFloat(), out value); } else if (p.IsBoolean()) { TypeConversion.TryConvert(p.AsBoolean(), out value); } else if (p.IsNull()) { value = default; } break; } default: { var metadata = view.Type == TokenType.Object ? GetSerializedContainerMetadata(view.AsObjectView()) : default; m_SerializedTypeProvider.View = view; m_SerializedTypeProvider.SerializedType = isRoot ? m_SerializedType : null; if (metadata.IsSerializedReference) { if (null == m_SerializedReferences) { m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, new Exception("Deserialization encountered a serialized object reference while running with DisableSerializedReferences."))); return; } value = (TValue)m_SerializedReferences.GetDeserializedReference(metadata.SerializedId); return; } try { DefaultTypeConstruction.Construct(ref value, m_SerializedTypeProvider); } catch (ArgumentException e) { m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, new ArgumentException(e.Message))); return; } if (metadata.HasSerializedId) { // This call is harmless to skip if we don't have serialized references. m_SerializedReferences?.AddDeserializedReference(metadata.SerializedId, value); } using (new SerializedContainerMetadataScope(this, metadata)) using (new UnsafeViewScope(this, view)) { if (!PropertyContainer.Visit(ref value, this, out var errorCode)) { switch (errorCode) { case VisitErrorCode.NullContainer: throw new ArgumentNullException(nameof(value)); case VisitErrorCode.InvalidContainerType: throw new InvalidContainerTypeException(value.GetType()); case VisitErrorCode.MissingPropertyBag: throw new MissingPropertyBagException(value.GetType()); default: throw new Exception($"Unexpected {nameof(VisitErrorCode)}=[{errorCode}]"); } } } break; } } }
public object Construct(Type type, UnsafeValueView view) { if (type != typeof(Component) || m_GameObject == null) { return(null); } try { var componentType = m_GenericConstructor.GetSerializedType(); if (componentType == null) { return(null); } #if !NET_DOTS && !ENABLE_IL2CPP SceneSerialization.RegisterPropertyBag(componentType); #endif var properties = PropertyBagStore.GetPropertyBag(componentType); if (properties == null) { Debug.LogWarning($"Could not resolve component type {componentType} deserializing {m_GameObject.name}. Will preserve serialized contents as JSON string"); return(CreateMissingComponent(view)); } if (componentType == typeof(MissingComponent)) { try { var value = new JsonObject(); var visitor = new JsonSceneReader(m_SerializationMetadata); visitor.SetView(view); PropertyContainer.Visit(ref value, visitor); var jsonString = value[nameof(MissingComponent.JsonString)].ToString(); // For some reason, newlines are read as null characters which break parsing jsonString = jsonString.Replace('\0', '\n'); using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString))) { using (var reader = new SerializedObjectReader(stream)) { reader.Read(out var document); var componentVisitor = new ComponentVisitor(m_GameObject, document.AsUnsafe(), null, m_SerializationMetadata); Component missingComponent = null; componentVisitor.ReadValue(ref missingComponent, document.AsUnsafe()); return(missingComponent); } } } catch (Exception e) { Debug.Log($"Encountered an exception trying to deserialize MissingComponent. Preserving it as-is. Exception follows:\n{e}"); } } return(componentType == typeof(Transform) ? m_GameObject.GetComponent <Transform>() : m_GameObject.AddComponent(componentType)); } catch (ArgumentException) { Debug.LogWarning($"Could not resolve component type deserializing {m_GameObject.name}. Will preserve serialized contents as JSON string"); return(CreateMissingComponent(view)); } }
protected void ReadValue <TValue>(ref TValue value, UnsafeValueView view, bool isRoot = false) { switch (view.Type) { case TokenType.String: { TypeConversion.TryConvert(view.AsStringView().ToString(), out value); break; } case TokenType.Primitive: { var p = view.AsPrimitiveView(); if (p.IsIntegral()) { if (p.IsSigned()) { TypeConversion.TryConvert(p.AsInt64(), out value); } else if (value is long) { TypeConversion.TryConvert(p.AsInt64(), out value); } else { TypeConversion.TryConvert(p.AsUInt64(), out value); } } else if (p.IsDecimal() || p.IsInfinity() || p.IsNaN()) { TypeConversion.TryConvert(p.AsFloat(), out value); } else if (p.IsBoolean()) { TypeConversion.TryConvert(p.AsBoolean(), out value); } else if (p.IsNull()) { value = default; } break; } default: { var metadata = view.Type == TokenType.Object ? GetSerializedContainerMetadata(view.AsObjectView()) : default; m_SerializedTypeProvider.View = view; m_SerializedTypeProvider.SerializedType = isRoot ? m_SerializedType : null; try { var customValue = m_CustomTypeConstructor?.Construct(typeof(TValue), view); if (customValue != null) { value = (TValue)customValue; } if (value == null) { DefaultTypeConstruction.Construct(ref value, m_SerializedTypeProvider); } } catch (ArgumentException e) { m_SerializedTypeProvider.Events.Add(new DeserializationEvent(EventType.Exception, new ArgumentException(e.Message))); return; } using (new SerializedContainerMetadataScope(this, metadata)) using (new UnsafeViewScope(this, view)) { var type = value?.GetType(); #if !NET_DOTS && !ENABLE_IL2CPP if (type != null) { SceneSerialization.RegisterPropertyBag(type); } #endif if (!PropertyContainer.Visit(ref value, this, out var errorCode)) { switch (errorCode) { case VisitErrorCode.NullContainer: throw new ArgumentNullException(nameof(value)); case VisitErrorCode.InvalidContainerType: throw new InvalidContainerTypeException(type); case VisitErrorCode.MissingPropertyBag: throw new MissingPropertyBagException(type); default: throw new Exception($"Unexpected {nameof(VisitErrorCode)}=[{errorCode}]"); } } } break; } } }