Browse Source

refactored json serialization to try to fit unknown objects

Vicente Penades 6 years ago
parent
commit
7ecbd3a6a9

+ 4 - 4
build/SharpGLTF.CodeGen/CodeGen/EmitCSharp.cs

@@ -526,7 +526,7 @@ namespace SharpGLTF.CodeGen
                     this.AddFieldSerializerCase(smethod);
 
                     // emit deserializer
-                    this.AddFieldDeserializerCase(f.PersistentName, $"{frname} = DeserializeValue<{_Emitter._GetRuntimeName(etype)}>(reader);");
+                    this.AddFieldDeserializerCase(f.PersistentName, $"{frname} = DeserializePropertyValue<{_Emitter._GetRuntimeName(etype)}>(reader);");
 
                     continue;
                 }
@@ -565,15 +565,15 @@ namespace SharpGLTF.CodeGen
             if (f.FieldType is ArrayType atype)
             {
                 var titem = _Emitter._GetRuntimeName(atype.ItemType);
-                return $"DeserializeList<{titem}>(reader, {fname});";
+                return $"DeserializePropertyList<{titem}>(reader, {fname});";
             }
             else if (f.FieldType is DictionaryType dtype)
             {
                 var titem = _Emitter._GetRuntimeName(dtype.ValueType);
-                return $"DeserializeDictionary<{titem}>(reader, {fname});";
+                return $"DeserializePropertyDictionary<{titem}>(reader, {fname});";
             }
 
-            return $"{fname} = DeserializeValue<{_Emitter._GetRuntimeName(f.FieldType)}>(reader);";
+            return $"{fname} = DeserializePropertyValue<{_Emitter._GetRuntimeName(f.FieldType)}>(reader);";
         }        
 
         public void AddFieldSerializerCase(string line) { _SerializerBody.Add(line); }

+ 117 - 105
src/SharpGLTF/IO/JsonSerializable.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Numerics;
 using System.Text;
 
 using Newtonsoft.Json;
@@ -19,7 +20,7 @@ namespace SharpGLTF.IO
 
         #region serialization
 
-        public void Serialize(JsonWriter writer)
+        internal void Serialize(JsonWriter writer)
         {
             writer.WriteStartObject();
             SerializeProperties(writer);
@@ -35,13 +36,6 @@ namespace SharpGLTF.IO
             _Serialize(writer, value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, string value)
-        {
-            if (value == null) return;
-            writer.WritePropertyName(name);
-            writer.WriteValue(value);
-        }
-
         protected static void SerializeProperty(JsonWriter writer, string name, Boolean? value, Boolean? defval = null)
         {
             if (!value.HasValue) return;
@@ -74,7 +68,7 @@ namespace SharpGLTF.IO
             writer.WriteValue(value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, System.Numerics.Vector2? value, System.Numerics.Vector2? defval = null)
+        protected static void SerializeProperty(JsonWriter writer, string name, Vector2? value, Vector2? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
@@ -82,7 +76,7 @@ namespace SharpGLTF.IO
             _Serialize(writer, value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, System.Numerics.Vector3? value, System.Numerics.Vector3? defval = null)
+        protected static void SerializeProperty(JsonWriter writer, string name, Vector3? value, Vector3? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
@@ -90,7 +84,7 @@ namespace SharpGLTF.IO
             _Serialize(writer, value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, System.Numerics.Vector4? value, System.Numerics.Vector4? defval = null)
+        protected static void SerializeProperty(JsonWriter writer, string name, Vector4? value, Vector4? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
@@ -98,7 +92,7 @@ namespace SharpGLTF.IO
             _Serialize(writer, value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, System.Numerics.Quaternion? value, System.Numerics.Quaternion? defval = null)
+        protected static void SerializeProperty(JsonWriter writer, string name, Quaternion? value, Quaternion? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
@@ -106,7 +100,7 @@ namespace SharpGLTF.IO
             _Serialize(writer, value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, System.Numerics.Matrix4x4? value, System.Numerics.Matrix4x4? defval = null)
+        protected static void SerializeProperty(JsonWriter writer, string name, Matrix4x4? value, Matrix4x4? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
@@ -193,11 +187,11 @@ namespace SharpGLTF.IO
             if (value is Double vfpd) { writer.WriteValue(vfpd); return; }
             if (value is Decimal vfpx) { writer.WriteValue(vfpx); return; }
 
-            if (value is System.Numerics.Vector2 vvv2) { writer.WriteVector2(vvv2); return; }
-            if (value is System.Numerics.Vector3 vvv3) { writer.WriteVector3(vvv3); return; }
-            if (value is System.Numerics.Vector4 vvv4) { writer.WriteVector4(vvv4); return; }
-            if (value is System.Numerics.Quaternion qqq4) { writer.WriteQuaternion(qqq4); return; }
-            if (value is System.Numerics.Matrix4x4 mm44) { writer.WriteMatrix4x4(mm44); return; }
+            if (value is Vector2 vvv2) { writer.WriteVector2(vvv2); return; }
+            if (value is Vector3 vvv3) { writer.WriteVector3(vvv3); return; }
+            if (value is Vector4 vvv4) { writer.WriteVector4(vvv4); return; }
+            if (value is Quaternion qqq4) { writer.WriteQuaternion(qqq4); return; }
+            if (value is Matrix4x4 mm44) { writer.WriteMatrix4x4(mm44); return; }
 
             if (value is JsonSerializable vgltf) { vgltf.Serialize(writer); return; }
 
@@ -246,124 +240,138 @@ namespace SharpGLTF.IO
 
         #region deserialization
 
-        public void Deserialize(JsonReader reader)
+        internal void Deserialize(JsonReader reader)
         {
-            while (reader.TokenType != JsonToken.StartObject)
-            {
-                reader.Read();
-            }
+            if (reader.TokenType == JsonToken.PropertyName) reader.Read();
 
-            while (reader.Read() && reader.TokenType != JsonToken.EndObject)
+            if (reader.TokenType == JsonToken.StartObject)
             {
-                if (reader.TokenType == JsonToken.PropertyName)
-                {
-                    var curProp = reader.Value.ToString();
-                    DeserializeProperty(reader, curProp);
-                }
-                else
+                while (reader.Read() && reader.TokenType != JsonToken.EndObject)
                 {
-                    throw new NotImplementedException(); // skip
+                    if (reader.TokenType == JsonToken.PropertyName)
+                    {
+                        var key = reader.Value as String;
+
+                        DeserializeProperty(key, reader);
+                    }
+                    else
+                    {
+                        throw new NotImplementedException();
+                    }
                 }
+
+                return;
             }
-        }
 
-        protected abstract void DeserializeProperty(JsonReader reader, string property);
+            throw new NotImplementedException();
+        }
 
         protected static Object DeserializeObject(JsonReader reader)
         {
-            reader.Read();
+            if (reader.TokenType == JsonToken.PropertyName) reader.Read();
 
-            if (reader.TokenType == JsonToken.StartObject)
+            if (reader.TokenType == JsonToken.StartArray)
             {
-                var dict = new Dictionary<string, object>();
+                var items = new List<Object>();
 
-                while (true)
+                while (reader.Read() && reader.TokenType != JsonToken.EndArray)
                 {
-                    reader.Read();
-
-                    if (reader.TokenType == JsonToken.StartObject) continue;
-                    if (reader.TokenType == JsonToken.EndObject) break;
-
-                    System.Diagnostics.Debug.Assert(reader.TokenType == JsonToken.PropertyName);
-                    var key = reader.Value as String;
-                    var val = DeserializeObject(reader);
-
-                    dict[key] = val;
+                    items.Add(DeserializeObject(reader));
                 }
 
-                return dict;
+                return items.ToArray();
             }
 
-            if (reader.TokenType == JsonToken.StartArray)
+            if (reader.TokenType == JsonToken.StartObject)
             {
-                var items = new List<Object>();
+                var dict = new Dictionary<string, object>();
 
-                while (true)
+                while (reader.Read() && reader.TokenType != JsonToken.EndObject)
                 {
-                    reader.Read();
-
-                    if (reader.TokenType == JsonToken.StartArray) continue;
-                    if (reader.TokenType == JsonToken.EndArray) break;
+                    if (reader.TokenType == JsonToken.PropertyName)
+                    {
+                        var key = reader.Value as String;
 
-                    items.Add(reader.Value);
+                        dict[key] = DeserializeObject(reader);
+                    }
+                    else
+                    {
+                        throw new JsonReaderException();
+                    }
                 }
 
-                return items.ToArray();
+                return dict;
             }
 
+            System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.None);
+            System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.EndArray);
+            System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.EndObject);
+            System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.EndConstructor);
+
             return reader.Value;
         }
 
-        protected static T DeserializeValue<T>(JsonReader reader)
-        {
-            reader.Read();
+        protected abstract void DeserializeProperty(string property, JsonReader reader);
 
+        protected static T DeserializePropertyValue<T>(JsonReader reader)
+        {
             _TryCastValue(reader, typeof(T), out Object v);
 
+            System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.StartArray);
+            System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.StartObject);
+            System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.PropertyName);
+            System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.StartConstructor);
+
             return (T)v;
         }
 
-        protected static void DeserializeValue<T>(JsonReader reader, Action<T> assign)
+        protected static void DeserializePropertyList<T>(JsonReader reader, IList<T> list)
         {
-            var value = DeserializeValue<T>(reader);
-            assign(value);
-        }
+            if (reader.TokenType == JsonToken.PropertyName) reader.Read();
 
-        protected static void DeserializeList<T>(JsonReader reader, IList<T> list)
-        {
-            // System.Diagnostics.Debug.Assert(typeof(T) != typeof(MeshPrimitive));
+            if (reader.TokenType != JsonToken.StartArray) throw new JsonReaderException();
+            if (reader.TokenType == JsonToken.StartObject) throw new JsonReaderException();
 
-            while (true)
-            {
-                reader.Read();
-
-                if (reader.TokenType == JsonToken.StartArray) continue;
-                if (reader.TokenType == JsonToken.EndArray) break;
+            var path2 = reader.Path;
 
+            while (reader.Read() && reader.TokenType != JsonToken.EndArray)
+            {
                 if (_TryCastValue(reader, typeof(T), out Object item))
                 {
                     list.Add((T)item);
                 }
+
+                System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.StartArray);
+                System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.StartObject);
+                System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.PropertyName);
+                System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.StartConstructor);
             }
+
+            System.Diagnostics.Debug.Assert(reader.TokenType == JsonToken.EndArray);
         }
 
-        protected static void DeserializeDictionary<T>(JsonReader reader, IDictionary<string, T> dict)
+        protected static void DeserializePropertyDictionary<T>(JsonReader reader, IDictionary<string, T> dict)
         {
-            while (true)
-            {
-                reader.Read();
+            if (reader.TokenType == JsonToken.PropertyName) reader.Read();
 
-                if (reader.TokenType == JsonToken.StartObject) continue;
-                if (reader.TokenType == JsonToken.EndObject) break;
+            if (reader.TokenType == JsonToken.StartArray) throw new JsonReaderException();
+            if (reader.TokenType != JsonToken.StartObject) throw new JsonReaderException();
 
-                System.Diagnostics.Debug.Assert(reader.TokenType == JsonToken.PropertyName);
-                var key = reader.Value as String;
+            while (reader.Read() && reader.TokenType != JsonToken.EndObject)
+            {
+                if (reader.TokenType == JsonToken.PropertyName)
+                {
+                    var key = reader.Value as String;
 
-                reader.Read();
+                    if (_TryCastValue(reader, typeof(T), out Object val))
+                    {
+                        dict[key] = (T)val;
+                    }
 
-                if (_TryCastValue(reader, typeof(T), out Object item))
-                {
-                    dict[key] = (T)item;
+                    System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.StartArray);
+                    System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.StartObject);
+                    System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.PropertyName);
+                    System.Diagnostics.Debug.Assert(reader.TokenType != JsonToken.StartConstructor);
                 }
             }
         }
@@ -373,8 +381,10 @@ namespace SharpGLTF.IO
             value = null;
 
             if (reader.TokenType == JsonToken.EndArray) return false;
-            if (reader.TokenType == JsonToken.EndConstructor) return false;
             if (reader.TokenType == JsonToken.EndObject) return false;
+            if (reader.TokenType == JsonToken.EndConstructor) return false;
+
+            if (reader.TokenType == JsonToken.PropertyName) reader.Read();
 
             // untangle nullable
             var ntype = Nullable.GetUnderlyingType(vtype);
@@ -382,8 +392,12 @@ namespace SharpGLTF.IO
 
             if (vtype == typeof(String) ||
                 vtype == typeof(Boolean) ||
+                vtype == typeof(Int16) ||
                 vtype == typeof(Int32) ||
                 vtype == typeof(Int64) ||
+                vtype == typeof(UInt16) ||
+                vtype == typeof(UInt32) ||
+                vtype == typeof(UInt64) ||
                 vtype == typeof(Single) ||
                 vtype == typeof(Double))
             {
@@ -400,43 +414,43 @@ namespace SharpGLTF.IO
                 throw new NotImplementedException();
             }
 
-            if (vtype == typeof(System.Numerics.Vector2))
+            if (vtype == typeof(Vector2))
             {
                 var l = new List<float>();
-                DeserializeList<float>(reader, l);
-                value = new System.Numerics.Vector2(l[0], l[1]);
+                DeserializePropertyList<float>(reader, l);
+                value = new Vector2(l[0], l[1]);
                 return true;
             }
 
-            if (vtype == typeof(System.Numerics.Vector3))
+            if (vtype == typeof(Vector3))
             {
                 var l = new List<float>();
-                DeserializeList<float>(reader, l);
-                value = new System.Numerics.Vector3(l[0], l[1], l[2]);
+                DeserializePropertyList<float>(reader, l);
+                value = new Vector3(l[0], l[1], l[2]);
                 return true;
             }
 
-            if (vtype == typeof(System.Numerics.Vector4))
+            if (vtype == typeof(Vector4))
             {
                 var l = new List<float>();
-                DeserializeList<float>(reader, l);
-                value = new System.Numerics.Vector4(l[0], l[1], l[2], l[3]);
+                DeserializePropertyList<float>(reader, l);
+                value = new Vector4(l[0], l[1], l[2], l[3]);
                 return true;
             }
 
-            if (vtype == typeof(System.Numerics.Quaternion))
+            if (vtype == typeof(Quaternion))
             {
                 var l = new List<float>();
-                DeserializeList<float>(reader, l);
+                DeserializePropertyList<float>(reader, l);
                 value = new System.Numerics.Quaternion(l[0], l[1], l[2], l[3]);
                 return true;
             }
 
-            if (vtype == typeof(System.Numerics.Matrix4x4))
+            if (vtype == typeof(Matrix4x4))
             {
                 var l = new List<float>();
-                DeserializeList<float>(reader, l);
-                value = new System.Numerics.Matrix4x4
+                DeserializePropertyList<float>(reader, l);
+                value = new Matrix4x4
                     (
                     l[0], l[1], l[2], l[3],
                     l[4], l[5], l[6], l[7],
@@ -448,11 +462,11 @@ namespace SharpGLTF.IO
 
             if (typeof(JsonSerializable).IsAssignableFrom(vtype))
             {
-                System.Diagnostics.Debug.Assert(reader.TokenType == JsonToken.StartObject);
-
                 var item = Activator.CreateInstance(vtype, true) as JsonSerializable;
 
+                System.Diagnostics.Debug.Assert(reader.TokenType == JsonToken.StartObject);
                 item.Deserialize(reader);
+                System.Diagnostics.Debug.Assert(reader.TokenType == JsonToken.EndObject);
 
                 value = item;
 
@@ -468,12 +482,10 @@ namespace SharpGLTF.IO
                     if (valType == typeof(Int32))
                     {
                         var dict = new Dictionary<string, Int32>();
-                        DeserializeDictionary(reader, dict);
+                        DeserializePropertyDictionary(reader, dict);
                         value = dict;
                         return true;
                     }
-
-                    // var dict = System.Activator.CreateInstance(vtype);
                 }
 
                 throw new NotImplementedException($"Can't deserialize {vtype}");

+ 11 - 5
src/SharpGLTF/Schema2/gltf.Extras.cs → src/SharpGLTF/IO/Unknown.cs

@@ -4,18 +4,24 @@ using System.Text;
 
 using Newtonsoft.Json;
 
-namespace SharpGLTF.Schema2
+namespace SharpGLTF.IO
 {
-    using IO;
-
-    class Extras : JsonSerializable
+    [System.Diagnostics.DebuggerDisplay("Unknown {_Name}")]
+    class Unknown : JsonSerializable
     {
+        public Unknown(string name) { this._Name = name; }
+
+        private readonly string _Name;
+
         private readonly Dictionary<string, Object> _Properties = new Dictionary<string, object>();
 
+        public string Name => _Name;
+
         public IDictionary<String, Object> Properties => _Properties;
 
-        protected override void DeserializeProperty(JsonReader reader, string property)
+        protected override void DeserializeProperty(string property, JsonReader reader)
         {
+            reader.Read();
             _Properties[property] = DeserializeObject(reader);
         }
 

+ 17 - 17
src/SharpGLTF/Schema2/Generated/ext.ModelLightsPunctual.g.cs

@@ -48,13 +48,13 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "innerConeAngle": _innerConeAngle = DeserializeValue<Double?>(reader); break;
-				case "outerConeAngle": _outerConeAngle = DeserializeValue<Double?>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "innerConeAngle": _innerConeAngle = DeserializePropertyValue<Double?>(reader); break;
+				case "outerConeAngle": _outerConeAngle = DeserializePropertyValue<Double?>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -93,16 +93,16 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "color": _color = DeserializeValue<Vector3?>(reader); break;
-				case "intensity": _intensity = DeserializeValue<Double?>(reader); break;
-				case "range": _range = DeserializeValue<Double?>(reader); break;
-				case "spot": _spot = DeserializeValue<PunctualLightSpot>(reader); break;
-				case "type": _type = DeserializeValue<String>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "color": _color = DeserializePropertyValue<Vector3?>(reader); break;
+				case "intensity": _intensity = DeserializePropertyValue<Double?>(reader); break;
+				case "range": _range = DeserializePropertyValue<Double?>(reader); break;
+				case "spot": _spot = DeserializePropertyValue<PunctualLightSpot>(reader); break;
+				case "type": _type = DeserializePropertyValue<String>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -123,12 +123,12 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "lights": DeserializeList<PunctualLight>(reader, _lights); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "lights": DeserializePropertyList<PunctualLight>(reader, _lights); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	

+ 4 - 4
src/SharpGLTF/Schema2/Generated/ext.NodeLightsPunctual.g.cs

@@ -39,12 +39,12 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "light": _light = DeserializeValue<Int32>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "light": _light = DeserializePropertyValue<Int32>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	

+ 7 - 7
src/SharpGLTF/Schema2/Generated/ext.TextureTransform.g.cs

@@ -55,15 +55,15 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "offset": _offset = DeserializeValue<Vector2?>(reader); break;
-				case "rotation": _rotation = DeserializeValue<Double?>(reader); break;
-				case "scale": _scale = DeserializeValue<Vector2?>(reader); break;
-				case "texCoord": _texCoord = DeserializeValue<Int32?>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "offset": _offset = DeserializePropertyValue<Vector2?>(reader); break;
+				case "rotation": _rotation = DeserializePropertyValue<Double?>(reader); break;
+				case "scale": _scale = DeserializePropertyValue<Vector2?>(reader); break;
+				case "texCoord": _texCoord = DeserializePropertyValue<Int32?>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	

+ 3 - 3
src/SharpGLTF/Schema2/Generated/ext.Unlit.g.cs

@@ -39,11 +39,11 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				default: base.DeserializeProperty(reader, property); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	

+ 8 - 8
src/SharpGLTF/Schema2/Generated/ext.pbrSpecularGlossiness.g.cs

@@ -59,16 +59,16 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "diffuseFactor": _diffuseFactor = DeserializeValue<Vector4?>(reader); break;
-				case "diffuseTexture": _diffuseTexture = DeserializeValue<TextureInfo>(reader); break;
-				case "glossinessFactor": _glossinessFactor = DeserializeValue<Double?>(reader); break;
-				case "specularFactor": _specularFactor = DeserializeValue<Vector3?>(reader); break;
-				case "specularGlossinessTexture": _specularGlossinessTexture = DeserializeValue<TextureInfo>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "diffuseFactor": _diffuseFactor = DeserializePropertyValue<Vector4?>(reader); break;
+				case "diffuseTexture": _diffuseTexture = DeserializePropertyValue<TextureInfo>(reader); break;
+				case "glossinessFactor": _glossinessFactor = DeserializePropertyValue<Double?>(reader); break;
+				case "specularFactor": _specularFactor = DeserializePropertyValue<Vector3?>(reader); break;
+				case "specularGlossinessTexture": _specularGlossinessTexture = DeserializePropertyValue<TextureInfo>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	

+ 199 - 199
src/SharpGLTF/Schema2/Generated/gltf.g.cs

@@ -183,12 +183,12 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "name": _name = DeserializeValue<String>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "name": _name = DeserializePropertyValue<String>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -219,14 +219,14 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "bufferView": _bufferView = DeserializeValue<Int32>(reader); break;
-				case "byteOffset": _byteOffset = DeserializeValue<Int32?>(reader); break;
-				case "componentType": _componentType = DeserializeValue<IndexEncodingType>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "bufferView": _bufferView = DeserializePropertyValue<Int32>(reader); break;
+				case "byteOffset": _byteOffset = DeserializePropertyValue<Int32?>(reader); break;
+				case "componentType": _componentType = DeserializePropertyValue<IndexEncodingType>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -254,13 +254,13 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "bufferView": _bufferView = DeserializeValue<Int32>(reader); break;
-				case "byteOffset": _byteOffset = DeserializeValue<Int32?>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "bufferView": _bufferView = DeserializePropertyValue<Int32>(reader); break;
+				case "byteOffset": _byteOffset = DeserializePropertyValue<Int32?>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -290,14 +290,14 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "count": _count = DeserializeValue<Int32>(reader); break;
-				case "indices": _indices = DeserializeValue<AccessorSparseIndices>(reader); break;
-				case "values": _values = DeserializeValue<AccessorSparseValues>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "count": _count = DeserializePropertyValue<Int32>(reader); break;
+				case "indices": _indices = DeserializePropertyValue<AccessorSparseIndices>(reader); break;
+				case "values": _values = DeserializePropertyValue<AccessorSparseValues>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -354,20 +354,20 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "bufferView": _bufferView = DeserializeValue<Int32?>(reader); break;
-				case "byteOffset": _byteOffset = DeserializeValue<Int32?>(reader); break;
-				case "componentType": _componentType = DeserializeValue<EncodingType>(reader); break;
-				case "count": _count = DeserializeValue<Int32>(reader); break;
-				case "max": DeserializeList<Double>(reader, _max); break;
-				case "min": DeserializeList<Double>(reader, _min); break;
-				case "normalized": _normalized = DeserializeValue<Boolean?>(reader); break;
-				case "sparse": _sparse = DeserializeValue<AccessorSparse>(reader); break;
-				case "type": _type = DeserializeValue<DimensionType>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "bufferView": _bufferView = DeserializePropertyValue<Int32?>(reader); break;
+				case "byteOffset": _byteOffset = DeserializePropertyValue<Int32?>(reader); break;
+				case "componentType": _componentType = DeserializePropertyValue<EncodingType>(reader); break;
+				case "count": _count = DeserializePropertyValue<Int32>(reader); break;
+				case "max": DeserializePropertyList<Double>(reader, _max); break;
+				case "min": DeserializePropertyList<Double>(reader, _min); break;
+				case "normalized": _normalized = DeserializePropertyValue<Boolean?>(reader); break;
+				case "sparse": _sparse = DeserializePropertyValue<AccessorSparse>(reader); break;
+				case "type": _type = DeserializePropertyValue<DimensionType>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -393,13 +393,13 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "node": _node = DeserializeValue<Int32?>(reader); break;
-				case "path": _path = DeserializeValue<PathType>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "node": _node = DeserializePropertyValue<Int32?>(reader); break;
+				case "path": _path = DeserializePropertyValue<PathType>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -425,13 +425,13 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "sampler": _sampler = DeserializeValue<Int32>(reader); break;
-				case "target": _target = DeserializeValue<AnimationChannelTarget>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "sampler": _sampler = DeserializePropertyValue<Int32>(reader); break;
+				case "target": _target = DeserializePropertyValue<AnimationChannelTarget>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -461,14 +461,14 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "input": _input = DeserializeValue<Int32>(reader); break;
-				case "interpolation": _interpolation = DeserializeValue<AnimationInterpolationMode>(reader); break;
-				case "output": _output = DeserializeValue<Int32>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "input": _input = DeserializePropertyValue<Int32>(reader); break;
+				case "interpolation": _interpolation = DeserializePropertyValue<AnimationInterpolationMode>(reader); break;
+				case "output": _output = DeserializePropertyValue<Int32>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -496,13 +496,13 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "channels": DeserializeList<AnimationChannel>(reader, _channels); break;
-				case "samplers": DeserializeList<AnimationSampler>(reader, _samplers); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "channels": DeserializePropertyList<AnimationChannel>(reader, _channels); break;
+				case "samplers": DeserializePropertyList<AnimationSampler>(reader, _samplers); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -534,15 +534,15 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "copyright": _copyright = DeserializeValue<String>(reader); break;
-				case "generator": _generator = DeserializeValue<String>(reader); break;
-				case "minVersion": _minVersion = DeserializeValue<String>(reader); break;
-				case "version": _version = DeserializeValue<String>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "copyright": _copyright = DeserializePropertyValue<String>(reader); break;
+				case "generator": _generator = DeserializePropertyValue<String>(reader); break;
+				case "minVersion": _minVersion = DeserializePropertyValue<String>(reader); break;
+				case "version": _version = DeserializePropertyValue<String>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -569,13 +569,13 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "byteLength": _byteLength = DeserializeValue<Int32>(reader); break;
-				case "uri": _uri = DeserializeValue<String>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "byteLength": _byteLength = DeserializePropertyValue<Int32>(reader); break;
+				case "uri": _uri = DeserializePropertyValue<String>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -615,16 +615,16 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "buffer": _buffer = DeserializeValue<Int32>(reader); break;
-				case "byteLength": _byteLength = DeserializeValue<Int32>(reader); break;
-				case "byteOffset": _byteOffset = DeserializeValue<Int32?>(reader); break;
-				case "byteStride": _byteStride = DeserializeValue<Int32?>(reader); break;
-				case "target": _target = DeserializeValue<BufferMode>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "buffer": _buffer = DeserializePropertyValue<Int32>(reader); break;
+				case "byteLength": _byteLength = DeserializePropertyValue<Int32>(reader); break;
+				case "byteOffset": _byteOffset = DeserializePropertyValue<Int32?>(reader); break;
+				case "byteStride": _byteStride = DeserializePropertyValue<Int32?>(reader); break;
+				case "target": _target = DeserializePropertyValue<BufferMode>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -658,15 +658,15 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "xmag": _xmag = DeserializeValue<Double>(reader); break;
-				case "ymag": _ymag = DeserializeValue<Double>(reader); break;
-				case "zfar": _zfar = DeserializeValue<Double>(reader); break;
-				case "znear": _znear = DeserializeValue<Double>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "xmag": _xmag = DeserializePropertyValue<Double>(reader); break;
+				case "ymag": _ymag = DeserializePropertyValue<Double>(reader); break;
+				case "zfar": _zfar = DeserializePropertyValue<Double>(reader); break;
+				case "znear": _znear = DeserializePropertyValue<Double>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -702,15 +702,15 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "aspectRatio": _aspectRatio = DeserializeValue<Double?>(reader); break;
-				case "yfov": _yfov = DeserializeValue<Double>(reader); break;
-				case "zfar": _zfar = DeserializeValue<Double?>(reader); break;
-				case "znear": _znear = DeserializeValue<Double>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "aspectRatio": _aspectRatio = DeserializePropertyValue<Double?>(reader); break;
+				case "yfov": _yfov = DeserializePropertyValue<Double>(reader); break;
+				case "zfar": _zfar = DeserializePropertyValue<Double?>(reader); break;
+				case "znear": _znear = DeserializePropertyValue<Double>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -740,14 +740,14 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "orthographic": _orthographic = DeserializeValue<CameraOrthographic>(reader); break;
-				case "perspective": _perspective = DeserializeValue<CameraPerspective>(reader); break;
-				case "type": _type = DeserializeValue<CameraType>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "orthographic": _orthographic = DeserializePropertyValue<CameraOrthographic>(reader); break;
+				case "perspective": _perspective = DeserializePropertyValue<CameraPerspective>(reader); break;
+				case "type": _type = DeserializePropertyValue<CameraType>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -775,13 +775,13 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "index": _index = DeserializeValue<Int32>(reader); break;
-				case "texCoord": _texCoord = DeserializeValue<Int32?>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "index": _index = DeserializePropertyValue<Int32>(reader); break;
+				case "texCoord": _texCoord = DeserializePropertyValue<Int32?>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -823,16 +823,16 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "baseColorFactor": _baseColorFactor = DeserializeValue<Vector4?>(reader); break;
-				case "baseColorTexture": _baseColorTexture = DeserializeValue<TextureInfo>(reader); break;
-				case "metallicFactor": _metallicFactor = DeserializeValue<Double?>(reader); break;
-				case "metallicRoughnessTexture": _metallicRoughnessTexture = DeserializeValue<TextureInfo>(reader); break;
-				case "roughnessFactor": _roughnessFactor = DeserializeValue<Double?>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "baseColorFactor": _baseColorFactor = DeserializePropertyValue<Vector4?>(reader); break;
+				case "baseColorTexture": _baseColorTexture = DeserializePropertyValue<TextureInfo>(reader); break;
+				case "metallicFactor": _metallicFactor = DeserializePropertyValue<Double?>(reader); break;
+				case "metallicRoughnessTexture": _metallicRoughnessTexture = DeserializePropertyValue<TextureInfo>(reader); break;
+				case "roughnessFactor": _roughnessFactor = DeserializePropertyValue<Double?>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -853,12 +853,12 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "scale": _scale = DeserializeValue<Double?>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "scale": _scale = DeserializePropertyValue<Double?>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -881,12 +881,12 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "strength": _strength = DeserializeValue<Double?>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "strength": _strength = DeserializePropertyValue<Double?>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -935,19 +935,19 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "alphaCutoff": _alphaCutoff = DeserializeValue<Double?>(reader); break;
-				case "alphaMode": _alphaMode = DeserializeValue<AlphaMode>(reader); break;
-				case "doubleSided": _doubleSided = DeserializeValue<Boolean?>(reader); break;
-				case "emissiveFactor": _emissiveFactor = DeserializeValue<Vector3?>(reader); break;
-				case "emissiveTexture": _emissiveTexture = DeserializeValue<TextureInfo>(reader); break;
-				case "normalTexture": _normalTexture = DeserializeValue<MaterialNormalTextureInfo>(reader); break;
-				case "occlusionTexture": _occlusionTexture = DeserializeValue<MaterialOcclusionTextureInfo>(reader); break;
-				case "pbrMetallicRoughness": _pbrMetallicRoughness = DeserializeValue<MaterialPBRMetallicRoughness>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "alphaCutoff": _alphaCutoff = DeserializePropertyValue<Double?>(reader); break;
+				case "alphaMode": _alphaMode = DeserializePropertyValue<AlphaMode>(reader); break;
+				case "doubleSided": _doubleSided = DeserializePropertyValue<Boolean?>(reader); break;
+				case "emissiveFactor": _emissiveFactor = DeserializePropertyValue<Vector3?>(reader); break;
+				case "emissiveTexture": _emissiveTexture = DeserializePropertyValue<TextureInfo>(reader); break;
+				case "normalTexture": _normalTexture = DeserializePropertyValue<MaterialNormalTextureInfo>(reader); break;
+				case "occlusionTexture": _occlusionTexture = DeserializePropertyValue<MaterialOcclusionTextureInfo>(reader); break;
+				case "pbrMetallicRoughness": _pbrMetallicRoughness = DeserializePropertyValue<MaterialPBRMetallicRoughness>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -984,16 +984,16 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "attributes": DeserializeDictionary<Int32>(reader, _attributes); break;
-				case "indices": _indices = DeserializeValue<Int32?>(reader); break;
-				case "material": _material = DeserializeValue<Int32?>(reader); break;
-				case "mode": _mode = DeserializeValue<PrimitiveType>(reader); break;
-				case "targets": DeserializeList<Dictionary<String,Int32>>(reader, _targets); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "attributes": DeserializePropertyDictionary<Int32>(reader, _attributes); break;
+				case "indices": _indices = DeserializePropertyValue<Int32?>(reader); break;
+				case "material": _material = DeserializePropertyValue<Int32?>(reader); break;
+				case "mode": _mode = DeserializePropertyValue<PrimitiveType>(reader); break;
+				case "targets": DeserializePropertyList<Dictionary<String,Int32>>(reader, _targets); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -1023,13 +1023,13 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "primitives": DeserializeList<MeshPrimitive>(reader, _primitives); break;
-				case "weights": DeserializeList<Double>(reader, _weights); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "primitives": DeserializePropertyList<MeshPrimitive>(reader, _primitives); break;
+				case "weights": DeserializePropertyList<Double>(reader, _weights); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -1080,20 +1080,20 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "camera": _camera = DeserializeValue<Int32?>(reader); break;
-				case "children": DeserializeList<Int32>(reader, _children); break;
-				case "matrix": _matrix = DeserializeValue<Matrix4x4?>(reader); break;
-				case "mesh": _mesh = DeserializeValue<Int32?>(reader); break;
-				case "rotation": _rotation = DeserializeValue<Quaternion?>(reader); break;
-				case "scale": _scale = DeserializeValue<Vector3?>(reader); break;
-				case "skin": _skin = DeserializeValue<Int32?>(reader); break;
-				case "translation": _translation = DeserializeValue<Vector3?>(reader); break;
-				case "weights": DeserializeList<Double>(reader, _weights); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "camera": _camera = DeserializePropertyValue<Int32?>(reader); break;
+				case "children": DeserializePropertyList<Int32>(reader, _children); break;
+				case "matrix": _matrix = DeserializePropertyValue<Matrix4x4?>(reader); break;
+				case "mesh": _mesh = DeserializePropertyValue<Int32?>(reader); break;
+				case "rotation": _rotation = DeserializePropertyValue<Quaternion?>(reader); break;
+				case "scale": _scale = DeserializePropertyValue<Vector3?>(reader); break;
+				case "skin": _skin = DeserializePropertyValue<Int32?>(reader); break;
+				case "translation": _translation = DeserializePropertyValue<Vector3?>(reader); break;
+				case "weights": DeserializePropertyList<Double>(reader, _weights); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -1127,15 +1127,15 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "magFilter": _magFilter = DeserializeValue<TextureInterpolationMode>(reader); break;
-				case "minFilter": _minFilter = DeserializeValue<TextureMipMapMode>(reader); break;
-				case "wrapS": _wrapS = DeserializeValue<TextureWrapMode>(reader); break;
-				case "wrapT": _wrapT = DeserializeValue<TextureWrapMode>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "magFilter": _magFilter = DeserializePropertyValue<TextureInterpolationMode>(reader); break;
+				case "minFilter": _minFilter = DeserializePropertyValue<TextureMipMapMode>(reader); break;
+				case "wrapS": _wrapS = DeserializePropertyValue<TextureWrapMode>(reader); break;
+				case "wrapT": _wrapT = DeserializePropertyValue<TextureWrapMode>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -1159,12 +1159,12 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "nodes": DeserializeList<Int32>(reader, _nodes); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "nodes": DeserializePropertyList<Int32>(reader, _nodes); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -1194,14 +1194,14 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "inverseBindMatrices": _inverseBindMatrices = DeserializeValue<Int32?>(reader); break;
-				case "joints": DeserializeList<Int32>(reader, _joints); break;
-				case "skeleton": _skeleton = DeserializeValue<Int32?>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "inverseBindMatrices": _inverseBindMatrices = DeserializePropertyValue<Int32?>(reader); break;
+				case "joints": DeserializePropertyList<Int32>(reader, _joints); break;
+				case "skeleton": _skeleton = DeserializePropertyValue<Int32?>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -1227,13 +1227,13 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "sampler": _sampler = DeserializeValue<Int32?>(reader); break;
-				case "source": _source = DeserializeValue<Int32?>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "sampler": _sampler = DeserializePropertyValue<Int32?>(reader); break;
+				case "source": _source = DeserializePropertyValue<Int32?>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -1319,28 +1319,28 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "asset": _asset = DeserializeValue<Asset>(reader); break;
-				case "extensionsRequired": DeserializeList<String>(reader, _extensionsRequired); break;
-				case "extensionsUsed": DeserializeList<String>(reader, _extensionsUsed); break;
-				case "accessors": DeserializeList<Accessor>(reader, _accessors); break;
-				case "animations": DeserializeList<Animation>(reader, _animations); break;
-				case "bufferViews": DeserializeList<BufferView>(reader, _bufferViews); break;
-				case "buffers": DeserializeList<Buffer>(reader, _buffers); break;
-				case "cameras": DeserializeList<Camera>(reader, _cameras); break;
-				case "images": DeserializeList<Image>(reader, _images); break;
-				case "materials": DeserializeList<Material>(reader, _materials); break;
-				case "meshes": DeserializeList<Mesh>(reader, _meshes); break;
-				case "nodes": DeserializeList<Node>(reader, _nodes); break;
-				case "samplers": DeserializeList<Sampler>(reader, _samplers); break;
-				case "scene": _scene = DeserializeValue<Int32?>(reader); break;
-				case "scenes": DeserializeList<Scene>(reader, _scenes); break;
-				case "skins": DeserializeList<Skin>(reader, _skins); break;
-				case "textures": DeserializeList<Texture>(reader, _textures); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "asset": _asset = DeserializePropertyValue<Asset>(reader); break;
+				case "extensionsRequired": DeserializePropertyList<String>(reader, _extensionsRequired); break;
+				case "extensionsUsed": DeserializePropertyList<String>(reader, _extensionsUsed); break;
+				case "accessors": DeserializePropertyList<Accessor>(reader, _accessors); break;
+				case "animations": DeserializePropertyList<Animation>(reader, _animations); break;
+				case "bufferViews": DeserializePropertyList<BufferView>(reader, _bufferViews); break;
+				case "buffers": DeserializePropertyList<Buffer>(reader, _buffers); break;
+				case "cameras": DeserializePropertyList<Camera>(reader, _cameras); break;
+				case "images": DeserializePropertyList<Image>(reader, _images); break;
+				case "materials": DeserializePropertyList<Material>(reader, _materials); break;
+				case "meshes": DeserializePropertyList<Mesh>(reader, _meshes); break;
+				case "nodes": DeserializePropertyList<Node>(reader, _nodes); break;
+				case "samplers": DeserializePropertyList<Sampler>(reader, _samplers); break;
+				case "scene": _scene = DeserializePropertyValue<Int32?>(reader); break;
+				case "scenes": DeserializePropertyList<Scene>(reader, _scenes); break;
+				case "skins": DeserializePropertyList<Skin>(reader, _skins); break;
+				case "textures": DeserializePropertyList<Texture>(reader, _textures); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	
@@ -1369,14 +1369,14 @@ namespace SharpGLTF.Schema2
 		}
 	
 		/// <inheritdoc />
-		protected override void DeserializeProperty(JsonReader reader, string property)
-		{
+		protected override void DeserializeProperty(string property, JsonReader reader)
+        {
 			switch (property)
 			{
-				case "bufferView": _bufferView = DeserializeValue<Int32?>(reader); break;
-				case "mimeType": _mimeType = DeserializeValue<String>(reader); break;
-				case "uri": _uri = DeserializeValue<String>(reader); break;
-				default: base.DeserializeProperty(reader, property); break;
+				case "bufferView": _bufferView = DeserializePropertyValue<Int32?>(reader); break;
+				case "mimeType": _mimeType = DeserializePropertyValue<String>(reader); break;
+				case "uri": _uri = DeserializePropertyValue<String>(reader); break;
+				default: base.DeserializeProperty(property, reader); break;
 			}
 		}
 	

+ 8 - 4
src/SharpGLTF/Schema2/gltf.ExtensionsFactory.cs

@@ -89,13 +89,17 @@ namespace SharpGLTF.Schema2
             this._extensionsUsed.AddRange(used);
         }
 
-        internal IEnumerable<string> RetrieveUsedExtensions()
+        internal IEnumerable<ExtraProperties> GetLogicalChildrenFlattened()
         {
-            // retrieve ALL the property based objects of the whole model.
-
-            var allObjects = GetLogicalChildren()
+            return GetLogicalChildren()
                 .SelectMany(item => ExtraProperties.Flatten(item)
                 .ToList());
+        }
+
+        internal IEnumerable<string> RetrieveUsedExtensions()
+        {
+            // retrieve ALL the property based objects of the whole model.
+            var allObjects = GetLogicalChildrenFlattened();
 
             // check all the extensions used by each object
             var used = new HashSet<string>();

+ 43 - 51
src/SharpGLTF/Schema2/gltf.ExtraProperties.cs

@@ -14,7 +14,7 @@ namespace SharpGLTF.Schema2
 
         private readonly List<JsonSerializable> _extensions = new List<JsonSerializable>();
 
-        private Extras _extras;
+        private readonly List<JsonSerializable> _extras = new List<JsonSerializable>();
 
         #endregion
 
@@ -28,14 +28,7 @@ namespace SharpGLTF.Schema2
         /// <summary>
         /// Gets a collection of extra dynamic properties.
         /// </summary>
-        public IDictionary<String, Object> Extras
-        {
-            get
-            {
-                if (_extras == null) _extras = new Extras();
-                return _extras.Properties;
-            }
-        }
+        public IReadOnlyCollection<JsonSerializable> Extras => _extras;
 
         #endregion
 
@@ -104,36 +97,49 @@ namespace SharpGLTF.Schema2
         {
             if (_extensions.Count > 0)
             {
-                var dict = new Dictionary<string, JsonSerializable>();
+                var dict = _ToDictionary(this, _extensions);
+                SerializeProperty(writer, "extensions", dict);
+            }
 
-                foreach (var val in this._extensions)
-                {
-                    if (val == null) continue;
-                    var key = ExtensionsFactory.Identify(this.GetType(), val.GetType());
-                    if (key == null) continue;
+            if (_extras != null)
+            {
+                var dict = _ToDictionary(this, _extras);
+                SerializeProperty(writer, "extras", dict);
+            }
+        }
 
-                    dict[key] = val;
-                }
+        private static IReadOnlyDictionary<string, JsonSerializable> _ToDictionary(JsonSerializable context, IEnumerable<JsonSerializable> serializables)
+        {
+            var dict = new Dictionary<string, JsonSerializable>();
 
-                SerializeProperty(writer, "extensions", dict);
+            foreach (var val in serializables)
+            {
+                if (val == null) continue;
+
+                string key = null;
+
+                if (val is Unknown unk) key = unk.Name;
+                else key = ExtensionsFactory.Identify(context.GetType(), val.GetType());
+
+                if (key == null) continue;
+                dict[key] = val;
             }
 
-            if (_extras != null) SerializeProperty(writer, "extras", _extras);
+            return dict;
         }
 
         /// <summary>
         /// Reads the properties of the current instance from a <see cref="JsonReader"/>.
         /// </summary>
-        /// <param name="reader">The source reader.</param>
         /// <param name="property">The name of the property.</param>
-        protected override void DeserializeProperty(JsonReader reader, string property)
+        /// <param name="reader">The source reader.</param>
+        protected override void DeserializeProperty(string property, JsonReader reader)
         {
             switch (property)
             {
                 case "extensions": _DeserializeExtensions(this, reader, _extensions); break;
 
-                // case "extras": reader.Skip(); break;
-                case "extras": _extras = DeserializeValue<Extras>(reader); break;
+                case "extras": _DeserializeExtensions(this, reader, _extras); break;
 
                 default: reader.Skip(); break;
             }
@@ -141,42 +147,28 @@ namespace SharpGLTF.Schema2
 
         private static void _DeserializeExtensions(JsonSerializable parent, JsonReader reader, IList<JsonSerializable> extensions)
         {
-            while (true)
+            reader.Read();
+
+            if (reader.TokenType == JsonToken.StartObject)
             {
-                reader.Read();
+                while (reader.Read() && reader.TokenType != JsonToken.EndObject)
+                {
+                    var key = reader.Value as String;
 
-                if (reader.TokenType == JsonToken.EndObject) break;
-                if (reader.TokenType == JsonToken.EndArray) break;
+                    var val = ExtensionsFactory.Create(parent, key);
 
-                if (reader.TokenType == JsonToken.StartArray)
-                {
-                    while (true)
+                    if (val != null)
                     {
-                        if (reader.TokenType == JsonToken.EndArray) break;
-
-                        _DeserializeExtensions(parent, reader, extensions);
+                        val.Deserialize(reader);
+                        extensions.Add(val);
+                        continue;
                     }
 
-                    break;
-                }
-
-                if (reader.TokenType == JsonToken.StartObject) continue;
-
-                System.Diagnostics.Debug.Assert(reader.TokenType == JsonToken.PropertyName);
-                var key = reader.Value as String;
-
-                var val = ExtensionsFactory.Create(parent, key);
-
-                if (val == null)
-                {
-                    reader.Skip();
-                }
-                else
-                {
-                    val.Deserialize(reader);
-                    extensions.Add(val);
+                    DeserializeObject(reader);
                 }
             }
+
+            reader.Skip();
         }
 
         #endregion

+ 2 - 0
src/SharpGLTF/Schema2/gltf.Serialization.cs

@@ -343,6 +343,8 @@ namespace SharpGLTF.Schema2
             using (var reader = new JsonTextReader(textReader))
             {
                 var root = new MODEL();
+
+                reader.Read();
                 root.Deserialize(reader);
 
                 var ex = root.Validate().FirstOrDefault();

+ 3 - 1
tests/SharpGLTF.Tests/Schema2/Authoring/CreateModelTests.cs

@@ -33,6 +33,8 @@ namespace SharpGLTF.Schema2.Authoring
             var root = ModelRoot.CreateModel();
             var scene = root.UseScene("Empty Scene");
 
+            /*
+
             root.Extras["author"] = "me";
 
             root.Extras["value1"] = 17;
@@ -64,7 +66,7 @@ namespace SharpGLTF.Schema2.Authoring
                 (
                 root.Extras["dict1"] as Dictionary<string, Object>,
                 rootBis.Extras["dict1"] as Dictionary<string, Object>
-                );
+                );*/
         }
 
         [Test(Description ="Creates a scene with lights")]

+ 23 - 11
tests/SharpGLTF.Tests/Schema2/LoadAndSave/LoadModelTests.cs

@@ -75,6 +75,7 @@ namespace SharpGLTF.Schema2.LoadAndSave
 
         [TestCase("\\glTF\\")]
         // [TestCase("\\glTF-Draco\\")] // Not supported
+        [TestCase("\\glTF-IBL\\")]
         [TestCase("\\glTF-Binary\\")]
         [TestCase("\\glTF-Embedded\\")]
         [TestCase("\\glTF-pbrSpecularGlossiness\\")]
@@ -87,12 +88,6 @@ namespace SharpGLTF.Schema2.LoadAndSave
             {
                 if (!f.Contains(section)) continue;
 
-                if (section.Contains("glTF-pbrSpecularGlossiness"))
-                {
-                    // these ones are included in the pbrSpecularGlossiness but don't actually contain any extension
-                    if (f.EndsWith("BoxInterleaved.gltf")) continue;
-                }
-
                 var model = GltfUtils.LoadModel(f);
                 Assert.NotNull(model);
 
@@ -100,16 +95,33 @@ namespace SharpGLTF.Schema2.LoadAndSave
                 model.AttachToCurrentTest(System.IO.Path.ChangeExtension(System.IO.Path.GetFileName(f), ".obj"));
                 model.AttachToCurrentTest(System.IO.Path.ChangeExtension(System.IO.Path.GetFileName(f), ".glb"));
                 
-                // do a model roundtrip
-                var bytes = model.WriteGLB();
-                var modelBis = ModelRoot.ParseGLB(bytes);
+                // do a model clone and compare it
+                _AssertAreEqual(model, model.DeepClone());
 
                 // check extensions used
-                var detectedExtensions = model.RetrieveUsedExtensions().ToArray();
-                CollectionAssert.AreEquivalent(model.ExtensionsUsed, detectedExtensions);
+                if (!model.ExtensionsUsed.Contains("EXT_lights_image_based"))
+                {
+                    var detectedExtensions = model.RetrieveUsedExtensions().ToArray();
+                    CollectionAssert.AreEquivalent(model.ExtensionsUsed, detectedExtensions);
+                }
             }
         }
 
+        private static void _AssertAreEqual(ModelRoot a, ModelRoot b)
+        {
+            var aa = a.GetLogicalChildrenFlattened().ToList();
+            var bb = b.GetLogicalChildrenFlattened().ToList();
+
+            Assert.AreEqual(aa.Count,bb.Count);
+
+            CollectionAssert.AreEqual
+                (
+                aa.Select(item => item.GetType()),
+                bb.Select(item => item.GetType())
+                );
+        }
+
+        [TestCase("SpecGlossVsMetalRough.gltf")]
         [TestCase(@"UnlitTest\glTF-Binary\UnlitTest.glb")]
         public void TestLoadSpecialCaseModels(string filePath)
         {