Sfoglia il codice sorgente

Json Serialization has been refactored to use the new System.Text.Json, which will allow faster serialization with less memory footprint.
Also, dependency with Newtonsoft.Json has been removed.

Vicente Penades 6 anni fa
parent
commit
b8c755435f
31 ha cambiato i file con 817 aggiunte e 671 eliminazioni
  1. 28 10
      build/SharpGLTF.CodeGen/CodeGen/EmitCSharp.cs
  2. 17 7
      src/SharpGLTF.Core/IO/BinarySerialization.cs
  3. 17 3
      src/SharpGLTF.Core/IO/JsonCollections.cs
  4. 140 175
      src/SharpGLTF.Core/IO/JsonSerializable.cs
  5. 93 96
      src/SharpGLTF.Core/IO/ReadContext.cs
  6. 170 48
      src/SharpGLTF.Core/IO/Serialization.cs
  7. 4 4
      src/SharpGLTF.Core/IO/Unknown.cs
  8. 8 6
      src/SharpGLTF.Core/IO/WriteContext.cs
  9. 1 1
      src/SharpGLTF.Core/Memory/ColorArray.cs
  10. 5 5
      src/SharpGLTF.Core/Schema2/Generated/ext.MSFT.textureDDS.g.cs
  11. 18 18
      src/SharpGLTF.Core/Schema2/Generated/ext.ModelLightsPunctual.g.cs
  12. 5 5
      src/SharpGLTF.Core/Schema2/Generated/ext.NodeLightsPunctual.g.cs
  13. 8 8
      src/SharpGLTF.Core/Schema2/Generated/ext.TextureTransform.g.cs
  14. 4 4
      src/SharpGLTF.Core/Schema2/Generated/ext.Unlit.g.cs
  15. 9 9
      src/SharpGLTF.Core/Schema2/Generated/ext.pbrSpecularGlossiness.g.cs
  16. 5 5
      src/SharpGLTF.Core/Schema2/Generated/ext.textureWEBP.g.cs
  17. 200 200
      src/SharpGLTF.Core/Schema2/Generated/gltf.g.cs
  18. 1 1
      src/SharpGLTF.Core/Schema2/gltf.Buffer.cs
  19. 13 11
      src/SharpGLTF.Core/Schema2/gltf.ExtraProperties.cs
  20. 1 1
      src/SharpGLTF.Core/Schema2/gltf.Images.cs
  21. 30 19
      src/SharpGLTF.Core/Schema2/gltf.Serialization.Read.cs
  22. 24 19
      src/SharpGLTF.Core/Schema2/gltf.Serialization.Write.cs
  23. 2 2
      src/SharpGLTF.Core/SharpGLTF.Core.csproj
  24. 1 1
      src/SharpGLTF.Core/Validation/ModelException.cs
  25. 1 1
      src/SharpGLTF.Core/Validation/ValidationContext.cs
  26. 2 5
      src/SharpGLTF.Toolkit/IO/Zip.cs
  27. 3 1
      tests/SharpGLTF.Tests/Collections/ChildrenCollectionTests.cs
  28. 1 1
      tests/SharpGLTF.Tests/Schema2/Authoring/BasicSceneCreationTests.cs
  29. 2 2
      tests/SharpGLTF.Tests/Schema2/LoadAndSave/LoadSpecialModelsTest.cs
  30. 3 2
      tests/SharpGLTF.Tests/SharpGLTF.Tests.csproj
  31. 1 1
      tests/SharpGLTF.Tests/Utils.cs

+ 28 - 10
build/SharpGLTF.CodeGen/CodeGen/EmitCSharp.cs

@@ -1,4 +1,6 @@
-using System;
+// #define USENEWTONSOFT
+
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Reflection;
@@ -331,7 +333,12 @@ namespace SharpGLTF.CodeGen
             sb.AppendLine("using System.Linq;");
             sb.AppendLine("using System.Text;");
             sb.AppendLine("using System.Numerics;");
+
+            #if USENEWTONSOFT
             sb.AppendLine("using Newtonsoft.Json;");
+            #else
+            sb.AppendLine("using System.Text.Json;");
+            #endif
             sb.AppendLine();
 
             sb.AppendLine($"namespace {Constants.OutputNamespace}");
@@ -471,7 +478,7 @@ namespace SharpGLTF.CodeGen
             yield return string.Empty;
         }            
 
-        #endregion
+#endregion
     }
 
     /// <summary>
@@ -503,6 +510,8 @@ namespace SharpGLTF.CodeGen
 
         public bool HasBaseClass { get; set; }
 
+        private const string _READERMODIFIER = "ref ";
+
         #endregion
 
         #region API
@@ -526,7 +535,7 @@ namespace SharpGLTF.CodeGen
                     this.AddFieldSerializerCase(smethod);
 
                     // emit deserializer
-                    this.AddFieldDeserializerCase(f.PersistentName, $"{frname} = DeserializePropertyValue<{_Emitter._GetRuntimeName(etype)}>(reader);");
+                    this.AddFieldDeserializerCase(f.PersistentName, $"{frname} = DeserializePropertyValue<{_Emitter._GetRuntimeName(etype)}>({_READERMODIFIER}reader);");
 
                     continue;
                 }
@@ -565,15 +574,15 @@ namespace SharpGLTF.CodeGen
             if (f.FieldType is ArrayType atype)
             {
                 var titem = _Emitter._GetRuntimeName(atype.ItemType);
-                return $"DeserializePropertyList<{titem}>(reader, {fname});";
+                return $"DeserializePropertyList<{titem}>({_READERMODIFIER}reader, {fname});";
             }
             else if (f.FieldType is DictionaryType dtype)
             {
                 var titem = _Emitter._GetRuntimeName(dtype.ValueType);
-                return $"DeserializePropertyDictionary<{titem}>(reader, {fname});";
+                return $"DeserializePropertyDictionary<{titem}>({_READERMODIFIER}reader, {fname});";
             }
 
-            return $"{fname} = DeserializePropertyValue<{_Emitter._GetRuntimeName(f.FieldType)}>(reader);";
+            return $"{fname} = DeserializePropertyValue<{_Emitter._GetRuntimeName(f.FieldType)}>({_READERMODIFIER}reader);";
         }        
 
         public void AddFieldSerializerCase(string line) { _SerializerBody.Add(line); }
@@ -585,6 +594,15 @@ namespace SharpGLTF.CodeGen
 
         public IEnumerable<string> EmitCode()
         {
+            #if USENEWTONSOFT
+            var readerType = "JsonReader";
+            var writerType = "JsonWriter";
+            #else
+            var readerType = "ref Utf8JsonReader";
+            var writerType = "Utf8JsonWriter";
+            #endif
+
+
             foreach (var l in ClassSummary.EmitSummary(0)) yield return l;
             
             yield return ClassDeclaration;
@@ -597,7 +615,7 @@ namespace SharpGLTF.CodeGen
             yield return string.Empty;
 
             // yield return "/// <inheritdoc />".Indent(1);
-            yield return "protected override void SerializeProperties(JsonWriter writer)".Indent(1);
+            yield return $"protected override void SerializeProperties({writerType} writer)".Indent(1);
             yield return "{".Indent(1);
             if (HasBaseClass) yield return "base.SerializeProperties(writer);".Indent(2);
             foreach (var l in _SerializerBody.Indent(2)) yield return l;
@@ -606,13 +624,13 @@ namespace SharpGLTF.CodeGen
             yield return string.Empty;
 
             // yield return "/// <inheritdoc />".Indent(1);
-            yield return "protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)".Indent(1);
+            yield return $"protected override void DeserializeProperty(string jsonPropertyName, {readerType} reader)".Indent(1);
             yield return "{".Indent(1);
             yield return "switch (jsonPropertyName)".Indent(2);
             yield return "{".Indent(2);
 
             foreach (var l in _DeserializerSwitchBody.Indent(3)) yield return l;
-            if (HasBaseClass) yield return "default: base.DeserializeProperty(jsonPropertyName, reader); break;".Indent(3);
+            if (HasBaseClass) yield return $"default: base.DeserializeProperty(jsonPropertyName,{_READERMODIFIER}reader); break;".Indent(3);
             else yield return "default: throw new NotImplementedException();".Indent(3);
 
             yield return "}".Indent(2);
@@ -623,6 +641,6 @@ namespace SharpGLTF.CodeGen
             yield return "}";
         }
 
-        #endregion
+#endregion
     }
 }

+ 17 - 7
src/SharpGLTF.Core/IO/BinarySerialization.cs

@@ -20,6 +20,17 @@ namespace SharpGLTF.Schema2
 
         #region read
 
+        public static bool IsBinaryHeader(Byte a, Byte b, Byte c, Byte d)
+        {
+            uint magic = 0;
+            magic |= (uint)a;
+            magic |= (uint)b << 8;
+            magic |= (uint)c << 16;
+            magic |= (uint)d << 24;
+
+            return magic == GLTFHEADER;
+        }
+
         internal static bool _Identify(Stream stream)
         {
             Guard.NotNull(stream, nameof(stream));
@@ -27,15 +38,14 @@ namespace SharpGLTF.Schema2
 
             var currPos = stream.Position;
 
-            uint magic = 0;
-            magic |= (uint)stream.ReadByte();
-            magic |= (uint)stream.ReadByte() << 8;
-            magic |= (uint)stream.ReadByte() << 16;
-            magic |= (uint)stream.ReadByte() << 24;
+            var a = stream.ReadByte();
+            var b = stream.ReadByte();
+            var c = stream.ReadByte();
+            var d = stream.ReadByte();
 
             stream.Position = currPos; // restart read position
 
-            return magic == GLTFHEADER;
+            return IsBinaryHeader((Byte)a, (Byte)b, (Byte)c, (Byte)d);
         }
 
         public static IReadOnlyDictionary<UInt32, Byte[]> ReadBinaryFile(Stream stream)
@@ -132,7 +142,7 @@ namespace SharpGLTF.Schema2
         {
             var ex = IsBinaryCompatible(model); if (ex != null) throw ex;
 
-            var jsonText = model.GetJSON(Newtonsoft.Json.Formatting.None);
+            var jsonText = model.GetJSON(false);
             var jsonChunk = Encoding.UTF8.GetBytes(jsonText);
             var jsonPadding = jsonChunk.Length & 3; if (jsonPadding != 0) jsonPadding = 4 - jsonPadding;
 

+ 17 - 3
src/SharpGLTF.Core/IO/Json.cs → src/SharpGLTF.Core/IO/JsonCollections.cs

@@ -2,12 +2,26 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
+using System.Text.Json;
 
 namespace SharpGLTF.IO
 {
     static class JsonUtils
     {
-        public static bool IsSerializable(Object value)
+        public static ArraySegment<Byte> ReadBytesToEnd(this System.IO.Stream s)
+        {
+            using (var m = new System.IO.MemoryStream())
+            {
+                s.CopyTo(m);
+                if (m.TryGetBuffer(out ArraySegment<Byte> segment)) return segment;
+
+                var array = m.ToArray();
+
+                return new ArraySegment<byte>(array);
+            }
+        }
+
+        public static bool IsJsonSerializable(Object value)
         {
             if (value == null) return false;
 
@@ -23,12 +37,12 @@ namespace SharpGLTF.IO
 
             if (value is JsonList list)
             {
-                return list.All(item => IsSerializable(item));
+                return list.All(item => IsJsonSerializable(item));
             }
 
             if (value is JsonDictionary dict)
             {
-                return dict.Values.All(item => IsSerializable(item));
+                return dict.Values.All(item => IsJsonSerializable(item));
             }
 
             return false;

+ 140 - 175
src/SharpGLTF.Core/IO/JsonSerializable.cs

@@ -4,7 +4,10 @@ using System.Linq;
 using System.Numerics;
 using System.Text;
 
-using Newtonsoft.Json;
+using System.Text.Json;
+
+using JSONEXCEPTION = System.Text.Json.JsonException;
+using JSONTOKEN = System.Text.Json.JsonTokenType;
 
 namespace SharpGLTF.IO
 {
@@ -34,7 +37,7 @@ namespace SharpGLTF.IO
 
         #region serialization
 
-        internal void Serialize(JsonWriter writer)
+        internal void Serialize(Utf8JsonWriter writer)
         {
             Guard.NotNull(writer, nameof(writer));
 
@@ -43,63 +46,58 @@ namespace SharpGLTF.IO
             writer.WriteEndObject();
         }
 
-        protected abstract void SerializeProperties(JsonWriter writer);
+        protected abstract void SerializeProperties(Utf8JsonWriter writer);
 
-        protected static void SerializeProperty(JsonWriter writer, string name, Object value)
+        protected static void SerializeProperty(Utf8JsonWriter writer, string name, Object value)
         {
             if (value == null) return;
 
             Guard.NotNull(writer, nameof(writer));
 
-            writer.WritePropertyName(name);
-            _Serialize(writer, value);
+            _SerializeProperty(writer, name, value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, Boolean? value, Boolean? defval = null)
+        protected static void SerializeProperty(Utf8JsonWriter writer, string name, Boolean? value, Boolean? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
 
             Guard.NotNull(writer, nameof(writer));
 
-            writer.WritePropertyName(name);
-            writer.WriteValue(value.Value);
+            writer.WriteBoolean(name, value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, Int32? value, Int32? defval = null)
+        protected static void SerializeProperty(Utf8JsonWriter writer, string name, Int32? value, Int32? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
 
             Guard.NotNull(writer, nameof(writer));
 
-            writer.WritePropertyName(name);
-            writer.WriteValue(value.Value);
+            writer.WriteNumber(name, value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, Single? value, Single? defval = null)
+        protected static void SerializeProperty(Utf8JsonWriter writer, string name, Single? value, Single? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
 
             Guard.NotNull(writer, nameof(writer));
 
-            writer.WritePropertyName(name);
-            writer.WriteValue(value.Value);
+            writer.WriteNumber(name, value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, Double? value, Double? defval = null)
+        protected static void SerializeProperty(Utf8JsonWriter writer, string name, Double? value, Double? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
 
             Guard.NotNull(writer, nameof(writer));
 
-            writer.WritePropertyName(name);
-            writer.WriteValue(value.Value);
+            writer.WriteNumber(name, value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, Vector2? value, Vector2? defval = null)
+        protected static void SerializeProperty(Utf8JsonWriter writer, string name, Vector2? value, Vector2? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
@@ -107,10 +105,10 @@ namespace SharpGLTF.IO
             Guard.NotNull(writer, nameof(writer));
 
             writer.WritePropertyName(name);
-            _Serialize(writer, value.Value);
+            writer.WriteVector2(value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, Vector3? value, Vector3? defval = null)
+        protected static void SerializeProperty(Utf8JsonWriter writer, string name, Vector3? value, Vector3? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
@@ -118,10 +116,10 @@ namespace SharpGLTF.IO
             Guard.NotNull(writer, nameof(writer));
 
             writer.WritePropertyName(name);
-            _Serialize(writer, value.Value);
+            writer.WriteVector3(value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, Vector4? value, Vector4? defval = null)
+        protected static void SerializeProperty(Utf8JsonWriter writer, string name, Vector4? value, Vector4? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
@@ -129,10 +127,10 @@ namespace SharpGLTF.IO
             Guard.NotNull(writer, nameof(writer));
 
             writer.WritePropertyName(name);
-            _Serialize(writer, value.Value);
+            writer.WriteVector4(value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, Quaternion? value, Quaternion? defval = null)
+        protected static void SerializeProperty(Utf8JsonWriter writer, string name, Quaternion? value, Quaternion? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
@@ -140,10 +138,10 @@ namespace SharpGLTF.IO
             Guard.NotNull(writer, nameof(writer));
 
             writer.WritePropertyName(name);
-            _Serialize(writer, value.Value);
+            writer.WriteQuaternion(value.Value);
         }
 
-        protected static void SerializeProperty(JsonWriter writer, string name, Matrix4x4? value, Matrix4x4? defval = null)
+        protected static void SerializeProperty(Utf8JsonWriter writer, string name, Matrix4x4? value, Matrix4x4? defval = null)
         {
             if (!value.HasValue) return;
             if (defval.HasValue && defval.Value.Equals(value.Value)) return;
@@ -151,10 +149,10 @@ namespace SharpGLTF.IO
             Guard.NotNull(writer, nameof(writer));
 
             writer.WritePropertyName(name);
-            _Serialize(writer, value.Value);
+            writer.WriteMatrix4x4(value.Value);
         }
 
-        protected static void SerializePropertyEnumValue<T>(JsonWriter writer, string name, T? value, T? defval = null)
+        protected static void SerializePropertyEnumValue<T>(Utf8JsonWriter writer, string name, T? value, T? defval = null)
             where T : struct
         {
             Guard.IsTrue(typeof(T).IsEnum, nameof(T));
@@ -164,10 +162,10 @@ namespace SharpGLTF.IO
 
             Guard.NotNull(writer, nameof(writer));
 
-            SerializeProperty(writer, name, (int)(Object)value);
+            writer.WriteNumber(name, (int)(Object)value);
         }
 
-        protected static void SerializePropertyEnumSymbol<T>(JsonWriter writer, string name, T? value, T? defval = null)
+        protected static void SerializePropertyEnumSymbol<T>(Utf8JsonWriter writer, string name, T? value, T? defval = null)
             where T : struct
         {
             Guard.IsTrue(typeof(T).IsEnum, nameof(T));
@@ -177,21 +175,20 @@ namespace SharpGLTF.IO
 
             Guard.NotNull(writer, nameof(writer));
 
-            SerializeProperty(writer, name, Enum.GetName(typeof(T), value));
+            writer.WriteString(name, Enum.GetName(typeof(T), value));
         }
 
-        protected static void SerializePropertyObject<T>(JsonWriter writer, string name, T value)
+        protected static void SerializePropertyObject<T>(Utf8JsonWriter writer, string name, T value)
             where T : JsonSerializable
         {
             if (value == null) return;
 
             Guard.NotNull(writer, nameof(writer));
 
-            writer.WritePropertyName(name);
-            _Serialize(writer, value);
+            _SerializeProperty(writer, name, value);
         }
 
-        protected static void SerializeProperty<T>(JsonWriter writer, string name, IReadOnlyList<T> collection, int? minItems = 1)
+        protected static void SerializeProperty<T>(Utf8JsonWriter writer, string name, IReadOnlyList<T> collection, int? minItems = 1)
         {
             if (collection == null) return;
             if (minItems.HasValue && collection.Count < minItems.Value) return;
@@ -201,15 +198,13 @@ namespace SharpGLTF.IO
             writer.WritePropertyName(name);
 
             writer.WriteStartArray();
-            foreach (var item in collection)
-            {
-                _Serialize(writer, item);
-            }
+
+            foreach (var item in collection) _SerializeValue(writer, item);
 
             writer.WriteEndArray();
         }
 
-        protected static void SerializeProperty<T>(JsonWriter writer, string name, IReadOnlyDictionary<String, T> collection)
+        protected static void SerializeProperty<T>(Utf8JsonWriter writer, string name, IReadOnlyDictionary<String, T> collection)
         {
             if (collection == null) return;
             if (collection.Count < 1) return;
@@ -219,44 +214,31 @@ namespace SharpGLTF.IO
             writer.WritePropertyName(name);
 
             writer.WriteStartObject();
-            foreach (var item in collection)
-            {
-                writer.WritePropertyName(item.Key);
-                _Serialize(writer, item.Value);
-            }
+
+            foreach (var item in collection) _SerializeProperty(writer, item.Key, item.Value);
 
             writer.WriteEndObject();
         }
 
-        private static void _Serialize(JsonWriter writer, Object value)
+        private static void _SerializeProperty(Utf8JsonWriter writer, String name, Object value)
         {
             Guard.NotNull(writer, nameof(writer));
             Guard.NotNull(value, nameof(value));
 
-            System.Diagnostics.Debug.Assert(!value.GetType().IsEnum, "gltf schema does not define a typed way of serializing enums");
+            if (writer.TryWriteProperty(name, value)) return;
 
-            if (value is String vstr) { writer.WriteValue(vstr); return; }
-            if (value is Boolean vbol) { writer.WriteValue(vbol); return; }
-
-            if (value is Byte vu8) { writer.WriteValue(vu8); return; }
-            if (value is UInt16 vu16) { writer.WriteValue(vu16); return; }
-            if (value is UInt32 vu32) { writer.WriteValue(vu32); return; }
-            if (value is UInt64 vu64) { writer.WriteValue(vu64); return; }
+            writer.WritePropertyName(name);
+            _SerializeValue(writer, value);
+        }
 
-            if (value is SByte vs8) { writer.WriteValue(vs8); return; }
-            if (value is Int16 vs16) { writer.WriteValue(vs16); return; }
-            if (value is Int32 vs32) { writer.WriteValue(vs32); return; }
-            if (value is Int64 vs64) { writer.WriteValue(vs64); return; }
+        private static void _SerializeValue(Utf8JsonWriter writer, Object value)
+        {
+            Guard.NotNull(writer, nameof(writer));
+            Guard.NotNull(value, nameof(value));
 
-            if (value is Single vf32) { writer.WriteValue(vf32); return; }
-            if (value is Double vf64) { writer.WriteValue(vf64); return; }
-            if (value is Decimal vfxx) { writer.WriteValue(vfxx); return; }
+            System.Diagnostics.Debug.Assert(!value.GetType().IsEnum, "gltf schema does not define a typed way of serializing enums");
 
-            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 (writer.TryWriteValue(value)) return;
 
             if (value is JsonSerializable vgltf) { vgltf.Serialize(writer); return; }
 
@@ -265,6 +247,7 @@ namespace SharpGLTF.IO
                 if (dict.Count == 0) return;
 
                 writer.WriteStartObject();
+
                 foreach (var key in dict.Keys)
                 {
                     var val = dict[key];
@@ -278,11 +261,11 @@ namespace SharpGLTF.IO
                         if (val is System.Collections.IDictionary xdict && xdict.Count == 0) continue;
                     }
 
-                    writer.WritePropertyName(key.ToString());
-                    _Serialize(writer, val);
+                    _SerializeProperty(writer, key.ToString(), val);
                 }
 
                 writer.WriteEndObject();
+
                 return;
             }
 
@@ -291,12 +274,14 @@ namespace SharpGLTF.IO
                 if (list.Count == 0) return;
 
                 writer.WriteStartArray();
+
                 foreach (var item in list)
                 {
-                    _Serialize(writer, item);
+                    _SerializeValue(writer, item);
                 }
 
                 writer.WriteEndArray();
+
                 return;
             }
 
@@ -307,21 +292,19 @@ namespace SharpGLTF.IO
 
         #region deserialization
 
-        internal void Deserialize(JsonReader reader)
+        internal void Deserialize(ref Utf8JsonReader reader)
         {
-            Guard.NotNull(reader, nameof(reader));
+            if (reader.TokenType == JSONTOKEN.PropertyName) reader.Read();
 
-            if (reader.TokenType == JsonToken.PropertyName) reader.Read();
-
-            if (reader.TokenType == JsonToken.StartObject)
+            if (reader.TokenType == JSONTOKEN.StartObject)
             {
-                while (reader.Read() && reader.TokenType != JsonToken.EndObject)
+                while (reader.Read() && reader.TokenType != JSONTOKEN.EndObject)
                 {
-                    if (reader.TokenType == JsonToken.PropertyName)
+                    if (reader.TokenType == JSONTOKEN.PropertyName)
                     {
-                        var key = reader.Value as String;
+                        var key = reader.GetString();
 
-                        DeserializeProperty(key, reader);
+                        DeserializeProperty(key, ref reader);
                     }
                     else
                     {
@@ -335,202 +318,184 @@ namespace SharpGLTF.IO
             throw new NotImplementedException();
         }
 
-        protected static Object DeserializeUnknownObject(JsonReader reader)
+        protected static Object DeserializeUnknownObject(ref Utf8JsonReader reader)
         {
-            Guard.NotNull(reader, nameof(reader));
-
-            if (reader.TokenType == JsonToken.PropertyName) reader.Read();
+            if (reader.TokenType == JSONTOKEN.PropertyName) reader.Read();
 
-            if (reader.TokenType == JsonToken.StartArray)
+            if (reader.TokenType == JSONTOKEN.StartArray)
             {
                 var list = new JsonList();
 
-                while (reader.Read() && reader.TokenType != JsonToken.EndArray)
+                while (reader.Read() && reader.TokenType != JSONTOKEN.EndArray)
                 {
-                    list.Add(DeserializeUnknownObject(reader));
+                    list.Add(DeserializeUnknownObject(ref reader));
                 }
 
                 return list;
             }
 
-            if (reader.TokenType == JsonToken.StartObject)
+            if (reader.TokenType == JSONTOKEN.StartObject)
             {
                 var dict = new JsonDictionary();
 
-                while (reader.Read() && reader.TokenType != JsonToken.EndObject)
+                while (reader.Read() && reader.TokenType != JSONTOKEN.EndObject)
                 {
-                    if (reader.TokenType == JsonToken.PropertyName)
+                    if (reader.TokenType == JSONTOKEN.PropertyName)
                     {
-                        var key = reader.Value as String;
+                        var key = reader.GetString();
 
-                        dict[key] = DeserializeUnknownObject(reader);
+                        dict[key] = DeserializeUnknownObject(ref reader);
                     }
                     else
                     {
-                        throw new JsonReaderException();
+                        throw new JSONEXCEPTION();
                     }
                 }
 
                 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);
+            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;
+            return reader.GetAnyValue();
         }
 
-        protected abstract void DeserializeProperty(string jsonPropertyName, JsonReader reader);
+        protected abstract void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader);
 
-        protected static T DeserializePropertyValue<T>(JsonReader reader)
+        protected static T DeserializePropertyValue<T>(ref Utf8JsonReader reader)
         {
-            Guard.NotNull(reader, nameof(reader));
+            _TryCastValue(ref reader, typeof(T), out Object v);
 
-            _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);
+            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 DeserializePropertyList<T>(JsonReader reader, IList<T> list)
+        protected static void DeserializePropertyList<T>(ref Utf8JsonReader reader, IList<T> list)
         {
-            Guard.NotNull(reader, nameof(reader));
+            // Guard.NotNull(reader, nameof(reader));
             Guard.NotNull(list, nameof(list));
 
-            if (reader.TokenType == JsonToken.PropertyName) reader.Read();
-
-            if (reader.TokenType != JsonToken.StartArray) throw new JsonReaderException();
-            if (reader.TokenType == JsonToken.StartObject) throw new JsonReaderException();
+            if (reader.TokenType == JSONTOKEN.PropertyName) reader.Read();
 
-            var path2 = reader.Path;
+            if (reader.TokenType != JSONTOKEN.StartArray) throw new JSONEXCEPTION();
+            if (reader.TokenType == JSONTOKEN.StartObject) throw new JSONEXCEPTION();
 
-            while (reader.Read() && reader.TokenType != JsonToken.EndArray)
+            while (reader.Read() && reader.TokenType != JSONTOKEN.EndArray)
             {
-                if (_TryCastValue(reader, typeof(T), out Object item))
+                if (_TryCastValue(ref 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.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);
+            System.Diagnostics.Debug.Assert(reader.TokenType == JSONTOKEN.EndArray);
         }
 
-        protected static void DeserializePropertyDictionary<T>(JsonReader reader, IDictionary<string, T> dict)
+        protected static void DeserializePropertyDictionary<T>(ref Utf8JsonReader reader, IDictionary<string, T> dict)
         {
-            Guard.NotNull(reader, nameof(reader));
             Guard.NotNull(dict, nameof(dict));
 
-            if (reader.TokenType == JsonToken.PropertyName) reader.Read();
+            if (reader.TokenType == JSONTOKEN.PropertyName) reader.Read();
 
-            if (reader.TokenType == JsonToken.StartArray) throw new JsonReaderException();
-            if (reader.TokenType != JsonToken.StartObject) throw new JsonReaderException();
+            if (reader.TokenType == JSONTOKEN.StartArray) throw new JSONEXCEPTION();
+            if (reader.TokenType != JSONTOKEN.StartObject) throw new JSONEXCEPTION();
 
-            while (reader.Read() && reader.TokenType != JsonToken.EndObject)
+            while (reader.Read() && reader.TokenType != JSONTOKEN.EndObject)
             {
-                if (reader.TokenType == JsonToken.PropertyName)
+                if (reader.TokenType == JSONTOKEN.PropertyName)
                 {
-                    var key = reader.Value as String;
+                    var key = reader.GetString();
 
-                    if (_TryCastValue(reader, typeof(T), out Object val))
+                    if (_TryCastValue(ref reader, typeof(T), out Object val))
                     {
                         dict[key] = (T)val;
                     }
 
-                    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.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);
                 }
             }
         }
 
-        private static bool _TryCastValue(JsonReader reader, Type vtype, out Object value)
+        private static bool _TryCastValue(ref Utf8JsonReader reader, Type vtype, out Object value)
         {
-            Guard.NotNull(reader, nameof(reader));
-
             value = null;
 
-            if (reader.TokenType == JsonToken.EndArray) return false;
-            if (reader.TokenType == JsonToken.EndObject) return false;
-            if (reader.TokenType == JsonToken.EndConstructor) return false;
+            if (reader.TokenType == JSONTOKEN.EndArray) return false;
+            if (reader.TokenType == JSONTOKEN.EndObject) return false;
+            // if (reader.TokenType == JsonToken.EndConstructor) return false;
 
-            if (reader.TokenType == JsonToken.PropertyName) reader.Read();
+            if (reader.TokenType == JSONTOKEN.PropertyName) reader.Read();
 
             // untangle nullable
             var ntype = Nullable.GetUnderlyingType(vtype);
             if (ntype != null) vtype = ntype;
 
-            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))
-            {
-                value = Convert.ChangeType(reader.Value, vtype, System.Globalization.CultureInfo.InvariantCulture);
-                return true;
-            }
+            if (vtype == typeof(String)) { value = reader.AsString(); return true; }
+            if (vtype == typeof(Boolean)) { value = reader.AsBoolean(); return true; }
 
-            if (vtype.IsEnum)
-            {
-                if (reader.Value is String xstrVal) { value = Enum.Parse(vtype, xstrVal, true); return true; }
-                if (reader.Value is Int32 int32Val) { value = Enum.ToObject(vtype, int32Val); return true; }
-                if (reader.Value is Int64 int64Val) { value = Enum.ToObject(vtype, int64Val); return true; }
+            if (vtype == typeof(Int16)) { value = reader.GetInt16(); return true; }
+            if (vtype == typeof(Int32)) { value = reader.GetInt32(); return true; }
+            if (vtype == typeof(Int64)) { value = reader.GetInt64(); return true; }
+            if (vtype == typeof(UInt16)) { value = reader.GetUInt16(); return true; }
+            if (vtype == typeof(UInt32)) { value = reader.GetUInt32(); return true; }
+            if (vtype == typeof(UInt64)) { value = reader.GetUInt64(); return true; }
+            if (vtype == typeof(Single)) { value = reader.GetSingle(); return true; }
+            if (vtype == typeof(Double)) { value = reader.GetDouble(); return true; }
+            if (vtype == typeof(Decimal)) { value = reader.GetDecimal(); return true; }
 
-                throw new NotImplementedException();
-            }
+            if (vtype.IsEnum) { value = reader.AsEnum(vtype); return true; }
 
             if (vtype == typeof(Vector2))
             {
-                var l = new List<float>();
-                DeserializePropertyList<float>(reader, l);
+                var l = new List<float>(2);
+                DeserializePropertyList<float>(ref reader, l);
                 value = new Vector2(l[0], l[1]);
                 return true;
             }
 
             if (vtype == typeof(Vector3))
             {
-                var l = new List<float>();
-                DeserializePropertyList<float>(reader, l);
+                var l = new List<float>(3);
+                DeserializePropertyList<float>(ref reader, l);
                 value = new Vector3(l[0], l[1], l[2]);
                 return true;
             }
 
             if (vtype == typeof(Vector4))
             {
-                var l = new List<float>();
-                DeserializePropertyList<float>(reader, l);
+                var l = new List<float>(4);
+                DeserializePropertyList<float>(ref reader, l);
                 value = new Vector4(l[0], l[1], l[2], l[3]);
                 return true;
             }
 
             if (vtype == typeof(Quaternion))
             {
-                var l = new List<float>();
-                DeserializePropertyList<float>(reader, l);
+                var l = new List<float>(4);
+                DeserializePropertyList<float>(ref reader, l);
                 value = new System.Numerics.Quaternion(l[0], l[1], l[2], l[3]);
                 return true;
             }
 
             if (vtype == typeof(Matrix4x4))
             {
-                var l = new List<float>();
-                DeserializePropertyList<float>(reader, l);
+                var l = new List<float>(16);
+                DeserializePropertyList<float>(ref reader, l);
                 value = new Matrix4x4
                     (
                     l[0], l[1], l[2], l[3],
@@ -545,9 +510,9 @@ namespace SharpGLTF.IO
             {
                 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);
+                System.Diagnostics.Debug.Assert(reader.TokenType == JSONTOKEN.StartObject);
+                item.Deserialize(ref reader);
+                System.Diagnostics.Debug.Assert(reader.TokenType == JSONTOKEN.EndObject);
 
                 value = item;
 
@@ -563,7 +528,7 @@ namespace SharpGLTF.IO
                     if (valType == typeof(Int32))
                     {
                         var dict = new Dictionary<string, Int32>();
-                        DeserializePropertyDictionary(reader, dict);
+                        DeserializePropertyDictionary(ref reader, dict);
                         value = dict;
                         return true;
                     }

+ 93 - 96
src/SharpGLTF.Core/IO/ReadContext.cs

@@ -4,7 +4,8 @@ using System.IO;
 using System.Linq;
 using System.Text;
 
-using Newtonsoft.Json;
+// using Newtonsoft.Json;
+using System.Text.Json;
 using SharpGLTF.Schema2;
 
 using BYTES = System.ArraySegment<byte>;
@@ -78,7 +79,7 @@ namespace SharpGLTF.IO
 
         #endregion
 
-        #region API
+        #region API - File System
 
         public BYTES ReadAllBytesToEnd(string fileName)
         {
@@ -102,22 +103,21 @@ namespace SharpGLTF.IO
             return new MemoryStream(content.Array, content.Offset, content.Count);
         }
 
-        public String ReadJson(Stream stream)
-        {
-            Guard.NotNull(stream, nameof(stream));
+        #endregion
 
-            bool binaryFile = BinarySerialization._Identify(stream);
+        #region API
 
-            if (binaryFile)
+        public Validation.ValidationResult Validate(string filePath)
+        {
+            using (var stream = File.OpenRead(filePath))
             {
-                var chunks = BinarySerialization.ReadBinaryFile(stream);
+                bool isBinary = BinarySerialization._Identify(stream);
 
-                return Encoding.UTF8.GetString(chunks[BinarySerialization.CHUNKJSON]);
-            }
+                if (isBinary) return _ReadGLB(stream).Validation;
 
-            using (var streamReader = new StreamReader(stream))
-            {
-                return streamReader.ReadToEnd();
+                var json = stream.ReadBytesToEnd();
+
+                return _Read(json).Validation;
             }
         }
 
@@ -129,41 +129,37 @@ namespace SharpGLTF.IO
         public SCHEMA2 ReadSchema2(Stream stream)
         {
             Guard.NotNull(stream, nameof(stream));
+            Guard.IsTrue(stream.CanRead, nameof(stream));
 
             bool binaryFile = BinarySerialization._Identify(stream);
 
             return binaryFile ? ReadBinarySchema2(stream) : ReadTextSchema2(stream);
         }
 
-        /// <summary>
-        /// Reads a <see cref="SCHEMA2"/> instance from a <see cref="Stream"/> containing a GLTF file.
-        /// </summary>
-        /// <param name="stream">A <see cref="Stream"/> to read from.</param>
-        /// <returns>A <see cref="SCHEMA2"/> instance.</returns>
-        public SCHEMA2 ReadTextSchema2(Stream stream)
+        internal SCHEMA2 _ReadFromDictionary(string fileName)
         {
-            Guard.NotNull(stream, nameof(stream));
+            var json = this.ReadAllBytesToEnd(fileName);
 
-            string content = null;
+            var mv = this._Read(json);
 
-            using (var streamReader = new StreamReader(stream))
-            {
-                content = streamReader.ReadToEnd();
-            }
+            if (mv.Validation.HasErrors) throw mv.Validation.Errors.FirstOrDefault();
 
-            return ParseJson(content);
+            return mv.Model;
         }
 
         /// <summary>
-        /// Reads a <see cref="SCHEMA2"/> instance from a <see cref="Stream"/> containing a GLB file.
+        /// Reads a <see cref="SCHEMA2"/> instance from a <see cref="Stream"/> containing a GLTF file.
         /// </summary>
         /// <param name="stream">A <see cref="Stream"/> to read from.</param>
         /// <returns>A <see cref="SCHEMA2"/> instance.</returns>
-        public SCHEMA2 ReadBinarySchema2(Stream stream)
+        public SCHEMA2 ReadTextSchema2(Stream stream)
         {
             Guard.NotNull(stream, nameof(stream));
+            Guard.IsTrue(stream.CanRead, nameof(stream));
+
+            var json = stream.ReadBytesToEnd();
 
-            var mv = _ReadGLB(stream);
+            var mv = this._Read(json);
 
             if (mv.Validation.HasErrors) throw mv.Validation.Errors.FirstOrDefault();
 
@@ -171,53 +167,22 @@ namespace SharpGLTF.IO
         }
 
         /// <summary>
-        /// Parses a <see cref="SCHEMA2"/> instance from a <see cref="String"/> JSON content representing a GLTF file.
+        /// Reads a <see cref="SCHEMA2"/> instance from a <see cref="Stream"/> containing a GLB file.
         /// </summary>
-        /// <param name="jsonContent">A <see cref="String"/> JSON content representing a GLTF file.</param>
+        /// <param name="stream">A <see cref="Stream"/> to read from.</param>
         /// <returns>A <see cref="SCHEMA2"/> instance.</returns>
-        public SCHEMA2 ParseJson(String jsonContent)
+        public SCHEMA2 ReadBinarySchema2(Stream stream)
         {
-            var mv = _ParseGLTF(jsonContent);
+            Guard.NotNull(stream, nameof(stream));
+            Guard.IsTrue(stream.CanRead, nameof(stream));
+
+            var mv = this._ReadGLB(stream);
 
             if (mv.Validation.HasErrors) throw mv.Validation.Errors.FirstOrDefault();
 
             return mv.Model;
         }
 
-        public Validation.ValidationResult Validate(string filePath)
-        {
-            using (var stream = File.OpenRead(filePath))
-            {
-                bool isBinary = BinarySerialization._Identify(stream);
-
-                if (isBinary) return _ReadGLB(stream).Validation;
-
-                string content = null;
-
-                using (var streamReader = new StreamReader(stream))
-                {
-                    content = streamReader.ReadToEnd();
-                }
-
-                return _ParseGLTF(content).Validation;
-            }
-        }
-
-        internal SCHEMA2 _ReadFromDictionary(string fileName)
-        {
-            using (var s = this.OpenFile(fileName))
-            {
-                using (var tr = new StreamReader(s))
-                {
-                    var mv = this._Read(tr);
-
-                    if (mv.Validation.HasErrors) throw mv.Validation.Errors.FirstOrDefault();
-
-                    return mv.Model;
-                }
-            }
-        }
-
         #endregion
 
         #region core
@@ -228,8 +193,6 @@ namespace SharpGLTF.IO
 
             var chunks = BinarySerialization.ReadBinaryFile(stream);
 
-            var dom = Encoding.UTF8.GetString(chunks[BinarySerialization.CHUNKJSON]);
-
             var context = this;
 
             if (chunks.ContainsKey(BinarySerialization.CHUNKBIN))
@@ -238,42 +201,35 @@ namespace SharpGLTF.IO
                 context._BinaryChunk = chunks[BinarySerialization.CHUNKBIN];
             }
 
-            return context._ParseGLTF(dom);
-        }
+            var jsonChunk = chunks[BinarySerialization.CHUNKJSON];
 
-        private (SCHEMA2 Model, Validation.ValidationResult Validation) _ParseGLTF(String jsonContent)
-        {
-            Guard.NotNullOrEmpty(jsonContent, nameof(jsonContent));
-            using (var tr = new StringReader(jsonContent))
-            {
-                return _Read(tr);
-            }
+            return context._Read(new BYTES(jsonChunk));
         }
 
-        private (SCHEMA2 Model, Validation.ValidationResult Validation) _Read(TextReader textReader)
+        private (SCHEMA2 Model, Validation.ValidationResult Validation) _Read(BYTES jsonUtf8Bytes)
         {
-            Guard.NotNull(textReader, nameof(textReader));
+            Guard.NotNull(jsonUtf8Bytes, nameof(jsonUtf8Bytes));
 
             var root = new SCHEMA2();
+
             var vcontext = new Validation.ValidationResult(root, this.Validation);
 
-            using (var reader = new JsonTextReader(textReader))
+            var reader = new Utf8JsonReader(jsonUtf8Bytes);
+
+            if (!reader.Read())
             {
-                if (!reader.Read())
-                {
-                    vcontext.AddError(new Validation.ModelException(root, "Json is empty"));
-                    return (null, vcontext);
-                }
-
-                try
-                {
-                    root.Deserialize(reader);
-                }
-                catch (JsonReaderException rex)
-                {
-                    vcontext.AddError(new Validation.SchemaException(root, rex));
-                    return (null, vcontext);
-                }
+                vcontext.AddError(new Validation.ModelException(root, "Json is empty"));
+                return (null, vcontext);
+            }
+
+            try
+            {
+                root.Deserialize(ref reader);
+            }
+            catch (JsonException rex)
+            {
+                vcontext.AddError(new Validation.SchemaException(root, rex));
+                return (null, vcontext);
             }
 
             // schema validation
@@ -299,5 +255,46 @@ namespace SharpGLTF.IO
         }
 
         #endregion
+
+        #region extras
+
+        public static String ReadJson(Stream stream)
+        {
+            Guard.NotNull(stream, nameof(stream));
+
+            bool binaryFile = BinarySerialization._Identify(stream);
+
+            if (binaryFile)
+            {
+                var chunks = BinarySerialization.ReadBinaryFile(stream);
+
+                return Encoding.UTF8.GetString(chunks[BinarySerialization.CHUNKJSON]);
+            }
+
+            using (var streamReader = new StreamReader(stream))
+            {
+                return streamReader.ReadToEnd();
+            }
+        }
+
+        public static BYTES ReadJsonBytes(Stream stream)
+        {
+            Guard.NotNull(stream, nameof(stream));
+
+            bool binaryFile = BinarySerialization._Identify(stream);
+
+            if (binaryFile)
+            {
+                var chunks = BinarySerialization.ReadBinaryFile(stream);
+
+                var jsonChunk = chunks[BinarySerialization.CHUNKJSON];
+
+                return new BYTES(jsonChunk);
+            }
+
+            return stream.ReadBytesToEnd();
+        }
+
+        #endregion
     }
 }

+ 170 - 48
src/SharpGLTF.Core/IO/Serialization.cs

@@ -1,89 +1,211 @@
 using System;
 using System.Collections.Generic;
+using System.Numerics;
 using System.Text;
-
-using Newtonsoft.Json;
+using System.Text.Json;
 
 namespace SharpGLTF.IO
 {
     static class _JSonSerializationExtensions
     {
-        public static Object GetValueAs(this JsonReader reader, Type vtype)
+        public static Boolean AsBoolean(this in Utf8JsonReader reader)
         {
-            System.Diagnostics.Debug.Assert
-                (
-                reader.TokenType == JsonToken.Boolean ||
-                reader.TokenType == JsonToken.String ||
-                reader.TokenType == JsonToken.Integer ||
-                reader.TokenType == JsonToken.Float,
-                $"invalid JSON token {reader.TokenType}"
-                );
-
-            return Convert.ChangeType(reader.Value, vtype, System.Globalization.CultureInfo.InvariantCulture);
+            switch (reader.TokenType)
+            {
+                case JsonTokenType.Null: return false;
+                case JsonTokenType.True: return true;
+                case JsonTokenType.False: return false;
+                case JsonTokenType.Number: return reader.GetInt32() != 0;
+                default: throw new NotImplementedException();
+            }
+        }
+
+        public static String AsString(this in Utf8JsonReader reader)
+        {
+            switch (reader.TokenType)
+            {
+                case JsonTokenType.Null: return null;
+                case JsonTokenType.String: return reader.GetString();
+                case JsonTokenType.PropertyName: return reader.GetString();
+                case JsonTokenType.True: return "true";
+                case JsonTokenType.False: return "false";
+                case JsonTokenType.Number: return reader.GetDecimal().ToString(System.Globalization.CultureInfo.InvariantCulture);
+                default: throw new NotImplementedException();
+            }
+        }
+
+        public static Object AsEnum(this in Utf8JsonReader reader, Type enumType)
+        {
+            if (reader.TokenType == JsonTokenType.String)
+            {
+                return Enum.Parse(enumType, reader.GetString(), true);
+            }
+
+            if (reader.TokenType == JsonTokenType.Number)
+            {
+                if (reader.TryGetInt32(out Int32 int32Val)) return Enum.ToObject(enumType, int32Val);
+                if (reader.TryGetInt64(out Int64 int64Val)) return Enum.ToObject(enumType, int64Val);
+            }
+
+            throw new NotImplementedException();
+        }
+
+        public static Object GetAnyValue(this in Utf8JsonReader reader)
+        {
+            switch (reader.TokenType)
+            {
+                case JsonTokenType.Null: return null;
+                case JsonTokenType.True: return true;
+                case JsonTokenType.False: return false;
+                case JsonTokenType.String: return reader.GetString();
+                case JsonTokenType.Number: return reader.GetDecimal();
+                case JsonTokenType.PropertyName: return reader.GetString();
+                default: throw new NotImplementedException();
+            }
+        }
+
+        public static Object GetValueAs(this in Utf8JsonReader reader, Type vtype)
+        {
+            System.Diagnostics.Debug.Assert(reader.TokenType != JsonTokenType.StartArray);
+            System.Diagnostics.Debug.Assert(reader.TokenType != JsonTokenType.EndArray);
+            System.Diagnostics.Debug.Assert(reader.TokenType != JsonTokenType.StartObject);
+            System.Diagnostics.Debug.Assert(reader.TokenType != JsonTokenType.EndObject);
+
+            if (reader.TokenType == JsonTokenType.Null) return null;
+
+            if (vtype == typeof(String)) { return reader.AsString(); }
+            if (vtype == typeof(Boolean)) { return reader.AsBoolean(); }
+            if (vtype == typeof(Int16)) { return reader.GetInt16(); }
+            if (vtype == typeof(Int32)) { return reader.GetInt32(); }
+            if (vtype == typeof(Int64)) { return reader.GetInt64(); }
+            if (vtype == typeof(UInt16)) { return reader.GetUInt16(); }
+            if (vtype == typeof(UInt32)) { return reader.GetUInt32(); }
+            if (vtype == typeof(UInt64)) { return reader.GetUInt64(); }
+            if (vtype == typeof(Single)) { return reader.GetSingle(); }
+            if (vtype == typeof(Double)) { return reader.GetDouble(); }
+            if (vtype == typeof(Decimal)) { return reader.GetDecimal(); }
+
+            return Convert.ChangeType(reader.GetString(), vtype, System.Globalization.CultureInfo.InvariantCulture);
         }
 
-        public static T GetValueAs<T>(this JsonReader reader)
+        public static T GetValueAs<T>(this in Utf8JsonReader reader)
             where T : struct
         {
             return (T)reader.GetValueAs(typeof(T));
         }
 
-        public static void WriteVector2(this JsonWriter writer, System.Numerics.Vector2 v)
+        public static bool TryWriteProperty(this Utf8JsonWriter writer, string property, Object value)
+        {
+            if (value is String vstr) { writer.WriteString(property, vstr); return true; }
+            if (value is Boolean vbol) { writer.WriteBoolean(property, vbol); return true; }
+
+            if (value is Byte vu8) { writer.WriteNumber(property, vu8); return true; }
+            if (value is UInt16 vu16) { writer.WriteNumber(property, vu16); return true; }
+            if (value is UInt32 vu32) { writer.WriteNumber(property, vu32); return true; }
+            if (value is UInt64 vu64) { writer.WriteNumber(property, vu64); return true; }
+
+            if (value is SByte vs8) { writer.WriteNumber(property, vs8); return true; }
+            if (value is Int16 vs16) { writer.WriteNumber(property, vs16); return true; }
+            if (value is Int32 vs32) { writer.WriteNumber(property, vs32); return true; }
+            if (value is Int64 vs64) { writer.WriteNumber(property, vs64); return true; }
+
+            if (value is Single vf32) { writer.WriteNumber(property, vf32); return true; }
+            if (value is Double vf64) { writer.WriteNumber(property, vf64); return true; }
+            if (value is Decimal vfxx) { writer.WriteNumber(property, vfxx); return true; }
+
+            if (value is Vector2 vvv2) { writer.WritePropertyName(property); writer.WriteVector2(vvv2); return true; }
+            if (value is Vector3 vvv3) { writer.WritePropertyName(property); writer.WriteVector3(vvv3); return true; }
+            if (value is Vector4 vvv4) { writer.WritePropertyName(property); writer.WriteVector4(vvv4); return true; }
+            if (value is Quaternion qqq4) { writer.WritePropertyName(property); writer.WriteQuaternion(qqq4); return true; }
+            if (value is Matrix4x4 mm44) { writer.WritePropertyName(property); writer.WriteMatrix4x4(mm44); return true; }
+
+            return false;
+        }
+
+        public static bool TryWriteValue(this Utf8JsonWriter writer, Object value)
+        {
+            if (value is String vstr) { writer.WriteStringValue(vstr); return true; }
+            if (value is Boolean vbol) { writer.WriteBooleanValue(vbol); return true; }
+
+            if (value is Byte vu8) { writer.WriteNumberValue(vu8); return true; }
+            if (value is UInt16 vu16) { writer.WriteNumberValue(vu16); return true; }
+            if (value is UInt32 vu32) { writer.WriteNumberValue(vu32); return true; }
+            if (value is UInt64 vu64) { writer.WriteNumberValue(vu64); return true; }
+
+            if (value is SByte vs8) { writer.WriteNumberValue(vs8); return true; }
+            if (value is Int16 vs16) { writer.WriteNumberValue(vs16); return true; }
+            if (value is Int32 vs32) { writer.WriteNumberValue(vs32); return true; }
+            if (value is Int64 vs64) { writer.WriteNumberValue(vs64); return true; }
+
+            if (value is Single vf32) { writer.WriteNumberValue(vf32); return true; }
+            if (value is Double vf64) { writer.WriteNumberValue(vf64); return true; }
+            if (value is Decimal vfxx) { writer.WriteNumberValue(vfxx); return true; }
+
+            if (value is Vector2 vvv2) { writer.WriteVector2(vvv2); return true; }
+            if (value is Vector3 vvv3) { writer.WriteVector3(vvv3); return true; }
+            if (value is Vector4 vvv4) { writer.WriteVector4(vvv4); return true; }
+            if (value is Quaternion qqq4) { writer.WriteQuaternion(qqq4); return true; }
+            if (value is Matrix4x4 mm44) { writer.WriteMatrix4x4(mm44); return true; }
+
+            return false;
+        }
+
+        public static void WriteVector2(this Utf8JsonWriter writer, Vector2 v)
         {
             writer.WriteStartArray();
-            writer.WriteValue(v.X);
-            writer.WriteValue(v.Y);
+            writer.WriteNumberValue(v.X);
+            writer.WriteNumberValue(v.Y);
             writer.WriteEndArray();
         }
 
-        public static void WriteVector3(this JsonWriter writer, System.Numerics.Vector3 v)
+        public static void WriteVector3(this Utf8JsonWriter writer, Vector3 v)
         {
             writer.WriteStartArray();
-            writer.WriteValue(v.X);
-            writer.WriteValue(v.Y);
-            writer.WriteValue(v.Z);
+            writer.WriteNumberValue(v.X);
+            writer.WriteNumberValue(v.Y);
+            writer.WriteNumberValue(v.Z);
             writer.WriteEndArray();
         }
 
-        public static void WriteVector4(this JsonWriter writer, System.Numerics.Vector4 v)
+        public static void WriteVector4(this Utf8JsonWriter writer, Vector4 v)
         {
             writer.WriteStartArray();
-            writer.WriteValue(v.X);
-            writer.WriteValue(v.Y);
-            writer.WriteValue(v.Z);
-            writer.WriteValue(v.W);
+            writer.WriteNumberValue(v.X);
+            writer.WriteNumberValue(v.Y);
+            writer.WriteNumberValue(v.Z);
+            writer.WriteNumberValue(v.W);
             writer.WriteEndArray();
         }
 
-        public static void WriteQuaternion(this JsonWriter writer, System.Numerics.Quaternion q)
+        public static void WriteQuaternion(this Utf8JsonWriter writer, Quaternion q)
         {
             writer.WriteStartArray();
-            writer.WriteValue(q.X);
-            writer.WriteValue(q.Y);
-            writer.WriteValue(q.Z);
-            writer.WriteValue(q.W);
+            writer.WriteNumberValue(q.X);
+            writer.WriteNumberValue(q.Y);
+            writer.WriteNumberValue(q.Z);
+            writer.WriteNumberValue(q.W);
             writer.WriteEndArray();
         }
 
-        public static void WriteMatrix4x4(this JsonWriter writer, System.Numerics.Matrix4x4 m)
+        public static void WriteMatrix4x4(this Utf8JsonWriter writer, Matrix4x4 m)
         {
             writer.WriteStartArray();
-            writer.WriteValue(m.M11);
-            writer.WriteValue(m.M12);
-            writer.WriteValue(m.M13);
-            writer.WriteValue(m.M14);
-            writer.WriteValue(m.M21);
-            writer.WriteValue(m.M22);
-            writer.WriteValue(m.M23);
-            writer.WriteValue(m.M24);
-            writer.WriteValue(m.M31);
-            writer.WriteValue(m.M32);
-            writer.WriteValue(m.M33);
-            writer.WriteValue(m.M34);
-            writer.WriteValue(m.M41);
-            writer.WriteValue(m.M42);
-            writer.WriteValue(m.M43);
-            writer.WriteValue(m.M44);
+            writer.WriteNumberValue(m.M11);
+            writer.WriteNumberValue(m.M12);
+            writer.WriteNumberValue(m.M13);
+            writer.WriteNumberValue(m.M14);
+            writer.WriteNumberValue(m.M21);
+            writer.WriteNumberValue(m.M22);
+            writer.WriteNumberValue(m.M23);
+            writer.WriteNumberValue(m.M24);
+            writer.WriteNumberValue(m.M31);
+            writer.WriteNumberValue(m.M32);
+            writer.WriteNumberValue(m.M33);
+            writer.WriteNumberValue(m.M34);
+            writer.WriteNumberValue(m.M41);
+            writer.WriteNumberValue(m.M42);
+            writer.WriteNumberValue(m.M43);
+            writer.WriteNumberValue(m.M44);
             writer.WriteEndArray();
         }
     }

+ 4 - 4
src/SharpGLTF.Core/IO/Unknown.cs

@@ -2,7 +2,7 @@
 using System.Collections.Generic;
 using System.Text;
 
-using Newtonsoft.Json;
+using System.Text.Json;
 
 namespace SharpGLTF.IO
 {
@@ -19,13 +19,13 @@ namespace SharpGLTF.IO
 
         public JsonDictionary Properties => _Properties;
 
-        protected override void DeserializeProperty(string property, JsonReader reader)
+        protected override void DeserializeProperty(string property, ref Utf8JsonReader reader)
         {
             reader.Read();
-            _Properties[property] = DeserializeUnknownObject(reader);
+            _Properties[property] = DeserializeUnknownObject(ref reader);
         }
 
-        protected override void SerializeProperties(JsonWriter writer)
+        protected override void SerializeProperties(Utf8JsonWriter writer)
         {
             foreach (var kvp in _Properties)
             {

+ 8 - 6
src/SharpGLTF.Core/IO/WriteContext.cs

@@ -4,7 +4,6 @@ using System.IO;
 using System.Linq;
 using System.Text;
 
-using Newtonsoft.Json;
 using SharpGLTF.Schema2;
 
 using BYTES = System.ArraySegment<byte>;
@@ -53,7 +52,7 @@ namespace SharpGLTF.IO
 
             var context = Create((fn, d) => File.WriteAllBytes(Path.Combine(dirPath, fn), d.ToArray()));
             context.ImageWriting = ResourceWriteMode.SatelliteFile;
-            context.JsonFormatting = Formatting.Indented;
+            context.JsonIndented = true;
             return context;
         }
 
@@ -64,7 +63,7 @@ namespace SharpGLTF.IO
             var context = Create((fn, buff) => dict[fn] = buff);
             context.ImageWriting = ResourceWriteMode.SatelliteFile;
             context.MergeBuffers = false;
-            context.JsonFormatting = Formatting.None;
+            context.JsonIndented = false;
 
             return context;
         }
@@ -77,7 +76,7 @@ namespace SharpGLTF.IO
             var context = Create((fn, d) => stream.Write(d.Array, d.Offset, d.Count));
             context.ImageWriting = ResourceWriteMode.Embedded;
             context.MergeBuffers = true;
-            context.JsonFormatting = Formatting.None;
+            context.JsonIndented = false;
 
             return context.WithBinarySettings();
         }
@@ -86,7 +85,7 @@ namespace SharpGLTF.IO
         {
             ImageWriting = ResourceWriteMode.BufferView;
             MergeBuffers = true;
-            JsonFormatting = Formatting.None;
+            JsonIndented = false;
 
             return this;
         }
@@ -157,10 +156,13 @@ namespace SharpGLTF.IO
 
             using (var m = new MemoryStream())
             {
+                model._WriteJSON(m, this.JsonIndented);
+
+                /*
                 using (var w = new StreamWriter(m))
                 {
                     model._WriteJSON(w, this.JsonFormatting);
-                }
+                }*/
 
                 WriteAllBytesToEnd($"{baseName}.gltf", m.ToArraySegment());
             }

+ 1 - 1
src/SharpGLTF.Core/Memory/ColorArray.cs

@@ -33,7 +33,7 @@ namespace SharpGLTF.Memory
         /// <param name="normalized">True if values are normalized.</param>
         /// <param name="defaultW">If <paramref name="dimensions"/> is 3, the W values are filled with this value</param>
         public ColorArray(Byte[] source, int byteOffset, int itemsCount, int byteStride, int dimensions = 4, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false, Single defaultW = 1)
-            : this(new BYTES(source), byteOffset, itemsCount, byteStride, dimensions, encoding, normalized)
+            : this(new BYTES(source), byteOffset, itemsCount, byteStride, dimensions, encoding, normalized, defaultW)
         { }
 
         /// <summary>

+ 5 - 5
src/SharpGLTF.Core/Schema2/Generated/ext.MSFT.textureDDS.g.cs

@@ -19,7 +19,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Numerics;
-using Newtonsoft.Json;
+using System.Text.Json;
 
 namespace SharpGLTF.Schema2
 {
@@ -34,18 +34,18 @@ namespace SharpGLTF.Schema2
 		private Int32? _source;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "source", _source);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "source": _source = DeserializePropertyValue<Int32?>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "source": _source = DeserializePropertyValue<Int32?>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	

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

@@ -19,7 +19,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Numerics;
-using Newtonsoft.Json;
+using System.Text.Json;
 
 namespace SharpGLTF.Schema2
 {
@@ -39,20 +39,20 @@ namespace SharpGLTF.Schema2
 		private Double? _outerConeAngle = _outerConeAngleDefault;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "innerConeAngle", _innerConeAngle, _innerConeAngleDefault);
 			SerializeProperty(writer, "outerConeAngle", _outerConeAngle, _outerConeAngleDefault);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "innerConeAngle": _innerConeAngle = DeserializePropertyValue<Double?>(reader); break;
-				case "outerConeAngle": _outerConeAngle = DeserializePropertyValue<Double?>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "innerConeAngle": _innerConeAngle = DeserializePropertyValue<Double?>(ref reader); break;
+				case "outerConeAngle": _outerConeAngle = DeserializePropertyValue<Double?>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -79,7 +79,7 @@ namespace SharpGLTF.Schema2
 		private String _type;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "color", _color, _colorDefault);
@@ -89,16 +89,16 @@ namespace SharpGLTF.Schema2
 			SerializeProperty(writer, "type", _type);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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(jsonPropertyName, reader); break;
+				case "color": _color = DeserializePropertyValue<Vector3?>(ref reader); break;
+				case "intensity": _intensity = DeserializePropertyValue<Double?>(ref reader); break;
+				case "range": _range = DeserializePropertyValue<Double?>(ref reader); break;
+				case "spot": _spot = DeserializePropertyValue<PunctualLightSpot>(ref reader); break;
+				case "type": _type = DeserializePropertyValue<String>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -111,18 +111,18 @@ namespace SharpGLTF.Schema2
 		private ChildrenCollection<PunctualLight,ModelRoot> _lights;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "lights", _lights, _lightsMinItems);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "lights": DeserializePropertyList<PunctualLight>(reader, _lights); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "lights": DeserializePropertyList<PunctualLight>(ref reader, _lights); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	

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

@@ -19,7 +19,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Numerics;
-using Newtonsoft.Json;
+using System.Text.Json;
 
 namespace SharpGLTF.Schema2
 {
@@ -31,18 +31,18 @@ namespace SharpGLTF.Schema2
 		private Int32 _light;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "light", _light);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "light": _light = DeserializePropertyValue<Int32>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "light": _light = DeserializePropertyValue<Int32>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	

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

@@ -19,7 +19,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Numerics;
-using Newtonsoft.Json;
+using System.Text.Json;
 
 namespace SharpGLTF.Schema2
 {
@@ -44,7 +44,7 @@ namespace SharpGLTF.Schema2
 		private Int32? _texCoord;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "offset", _offset, _offsetDefault);
@@ -53,15 +53,15 @@ namespace SharpGLTF.Schema2
 			SerializeProperty(writer, "texCoord", _texCoord);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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(jsonPropertyName, reader); break;
+				case "offset": _offset = DeserializePropertyValue<Vector2?>(ref reader); break;
+				case "rotation": _rotation = DeserializePropertyValue<Double?>(ref reader); break;
+				case "scale": _scale = DeserializePropertyValue<Vector2?>(ref reader); break;
+				case "texCoord": _texCoord = DeserializePropertyValue<Int32?>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	

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

@@ -19,7 +19,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Numerics;
-using Newtonsoft.Json;
+using System.Text.Json;
 
 namespace SharpGLTF.Schema2
 {
@@ -32,16 +32,16 @@ namespace SharpGLTF.Schema2
 	{
 	
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	

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

@@ -19,7 +19,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Numerics;
-using Newtonsoft.Json;
+using System.Text.Json;
 
 namespace SharpGLTF.Schema2
 {
@@ -47,7 +47,7 @@ namespace SharpGLTF.Schema2
 		private TextureInfo _specularGlossinessTexture;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "diffuseFactor", _diffuseFactor, _diffuseFactorDefault);
@@ -57,16 +57,16 @@ namespace SharpGLTF.Schema2
 			SerializePropertyObject(writer, "specularGlossinessTexture", _specularGlossinessTexture);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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(jsonPropertyName, reader); break;
+				case "diffuseFactor": _diffuseFactor = DeserializePropertyValue<Vector4?>(ref reader); break;
+				case "diffuseTexture": _diffuseTexture = DeserializePropertyValue<TextureInfo>(ref reader); break;
+				case "glossinessFactor": _glossinessFactor = DeserializePropertyValue<Double?>(ref reader); break;
+				case "specularFactor": _specularFactor = DeserializePropertyValue<Vector3?>(ref reader); break;
+				case "specularGlossinessTexture": _specularGlossinessTexture = DeserializePropertyValue<TextureInfo>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	

+ 5 - 5
src/SharpGLTF.Core/Schema2/Generated/ext.textureWEBP.g.cs

@@ -19,7 +19,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Numerics;
-using Newtonsoft.Json;
+using System.Text.Json;
 
 namespace SharpGLTF.Schema2
 {
@@ -34,18 +34,18 @@ namespace SharpGLTF.Schema2
 		private Int32? _source;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "source", _source);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "source": _source = DeserializePropertyValue<Int32?>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "source": _source = DeserializePropertyValue<Int32?>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	

+ 200 - 200
src/SharpGLTF.Core/Schema2/Generated/gltf.g.cs

@@ -19,7 +19,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Numerics;
-using Newtonsoft.Json;
+using System.Text.Json;
 
 namespace SharpGLTF.Schema2
 {
@@ -177,18 +177,18 @@ namespace SharpGLTF.Schema2
 		private String _name;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "name", _name);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "name": _name = DeserializePropertyValue<String>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "name": _name = DeserializePropertyValue<String>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -209,7 +209,7 @@ namespace SharpGLTF.Schema2
 		private IndexEncodingType _componentType;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "bufferView", _bufferView);
@@ -217,14 +217,14 @@ namespace SharpGLTF.Schema2
 			SerializePropertyEnumValue<IndexEncodingType>(writer, "componentType", _componentType);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "bufferView": _bufferView = DeserializePropertyValue<Int32>(reader); break;
-				case "byteOffset": _byteOffset = DeserializePropertyValue<Int32?>(reader); break;
-				case "componentType": _componentType = DeserializePropertyValue<IndexEncodingType>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "bufferView": _bufferView = DeserializePropertyValue<Int32>(ref reader); break;
+				case "byteOffset": _byteOffset = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "componentType": _componentType = DeserializePropertyValue<IndexEncodingType>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -243,20 +243,20 @@ namespace SharpGLTF.Schema2
 		private Int32? _byteOffset = _byteOffsetDefault;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "bufferView", _bufferView);
 			SerializeProperty(writer, "byteOffset", _byteOffset, _byteOffsetDefault);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "bufferView": _bufferView = DeserializePropertyValue<Int32>(reader); break;
-				case "byteOffset": _byteOffset = DeserializePropertyValue<Int32?>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "bufferView": _bufferView = DeserializePropertyValue<Int32>(ref reader); break;
+				case "byteOffset": _byteOffset = DeserializePropertyValue<Int32?>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -276,7 +276,7 @@ namespace SharpGLTF.Schema2
 		private AccessorSparseValues _values;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "count", _count);
@@ -284,14 +284,14 @@ namespace SharpGLTF.Schema2
 			SerializePropertyObject(writer, "values", _values);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "count": _count = DeserializePropertyValue<Int32>(reader); break;
-				case "indices": _indices = DeserializePropertyValue<AccessorSparseIndices>(reader); break;
-				case "values": _values = DeserializePropertyValue<AccessorSparseValues>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "count": _count = DeserializePropertyValue<Int32>(ref reader); break;
+				case "indices": _indices = DeserializePropertyValue<AccessorSparseIndices>(ref reader); break;
+				case "values": _values = DeserializePropertyValue<AccessorSparseValues>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -332,7 +332,7 @@ namespace SharpGLTF.Schema2
 		private DimensionType _type;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "bufferView", _bufferView);
@@ -346,20 +346,20 @@ namespace SharpGLTF.Schema2
 			SerializePropertyEnumSymbol<DimensionType>(writer, "type", _type);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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(jsonPropertyName, reader); break;
+				case "bufferView": _bufferView = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "byteOffset": _byteOffset = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "componentType": _componentType = DeserializePropertyValue<EncodingType>(ref reader); break;
+				case "count": _count = DeserializePropertyValue<Int32>(ref reader); break;
+				case "max": DeserializePropertyList<Double>(ref reader, _max); break;
+				case "min": DeserializePropertyList<Double>(ref reader, _min); break;
+				case "normalized": _normalized = DeserializePropertyValue<Boolean?>(ref reader); break;
+				case "sparse": _sparse = DeserializePropertyValue<AccessorSparse>(ref reader); break;
+				case "type": _type = DeserializePropertyValue<DimensionType>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -376,20 +376,20 @@ namespace SharpGLTF.Schema2
 		private PropertyPath _path;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "node", _node);
 			SerializePropertyEnumSymbol<PropertyPath>(writer, "path", _path);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "node": _node = DeserializePropertyValue<Int32?>(reader); break;
-				case "path": _path = DeserializePropertyValue<PropertyPath>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "node": _node = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "path": _path = DeserializePropertyValue<PropertyPath>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -406,20 +406,20 @@ namespace SharpGLTF.Schema2
 		private AnimationChannelTarget _target;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "sampler", _sampler);
 			SerializePropertyObject(writer, "target", _target);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "sampler": _sampler = DeserializePropertyValue<Int32>(reader); break;
-				case "target": _target = DeserializePropertyValue<AnimationChannelTarget>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "sampler": _sampler = DeserializePropertyValue<Int32>(ref reader); break;
+				case "target": _target = DeserializePropertyValue<AnimationChannelTarget>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -439,7 +439,7 @@ namespace SharpGLTF.Schema2
 		private Int32 _output;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "input", _input);
@@ -447,14 +447,14 @@ namespace SharpGLTF.Schema2
 			SerializeProperty(writer, "output", _output);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "input": _input = DeserializePropertyValue<Int32>(reader); break;
-				case "interpolation": _interpolation = DeserializePropertyValue<AnimationInterpolationMode>(reader); break;
-				case "output": _output = DeserializePropertyValue<Int32>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "input": _input = DeserializePropertyValue<Int32>(ref reader); break;
+				case "interpolation": _interpolation = DeserializePropertyValue<AnimationInterpolationMode>(ref reader); break;
+				case "output": _output = DeserializePropertyValue<Int32>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -473,20 +473,20 @@ namespace SharpGLTF.Schema2
 		private ChildrenCollection<AnimationSampler,Animation> _samplers;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "channels", _channels, _channelsMinItems);
 			SerializeProperty(writer, "samplers", _samplers, _samplersMinItems);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "channels": DeserializePropertyList<AnimationChannel>(reader, _channels); break;
-				case "samplers": DeserializePropertyList<AnimationSampler>(reader, _samplers); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "channels": DeserializePropertyList<AnimationChannel>(ref reader, _channels); break;
+				case "samplers": DeserializePropertyList<AnimationSampler>(ref reader, _samplers); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -507,7 +507,7 @@ namespace SharpGLTF.Schema2
 		private String _version;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "copyright", _copyright);
@@ -516,15 +516,15 @@ namespace SharpGLTF.Schema2
 			SerializeProperty(writer, "version", _version);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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(jsonPropertyName, reader); break;
+				case "copyright": _copyright = DeserializePropertyValue<String>(ref reader); break;
+				case "generator": _generator = DeserializePropertyValue<String>(ref reader); break;
+				case "minVersion": _minVersion = DeserializePropertyValue<String>(ref reader); break;
+				case "version": _version = DeserializePropertyValue<String>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -542,20 +542,20 @@ namespace SharpGLTF.Schema2
 		private String _uri;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "byteLength", _byteLength);
 			SerializeProperty(writer, "uri", _uri);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "byteLength": _byteLength = DeserializePropertyValue<Int32>(reader); break;
-				case "uri": _uri = DeserializePropertyValue<String>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "byteLength": _byteLength = DeserializePropertyValue<Int32>(ref reader); break;
+				case "uri": _uri = DeserializePropertyValue<String>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -583,7 +583,7 @@ namespace SharpGLTF.Schema2
 		private BufferMode? _target;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "buffer", _buffer);
@@ -593,16 +593,16 @@ namespace SharpGLTF.Schema2
 			SerializePropertyEnumValue<BufferMode>(writer, "target", _target);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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(jsonPropertyName, reader); break;
+				case "buffer": _buffer = DeserializePropertyValue<Int32>(ref reader); break;
+				case "byteLength": _byteLength = DeserializePropertyValue<Int32>(ref reader); break;
+				case "byteOffset": _byteOffset = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "byteStride": _byteStride = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "target": _target = DeserializePropertyValue<BufferMode>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -625,7 +625,7 @@ namespace SharpGLTF.Schema2
 		private Double _znear;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "xmag", _xmag);
@@ -634,15 +634,15 @@ namespace SharpGLTF.Schema2
 			SerializeProperty(writer, "znear", _znear);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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(jsonPropertyName, reader); break;
+				case "xmag": _xmag = DeserializePropertyValue<Double>(ref reader); break;
+				case "ymag": _ymag = DeserializePropertyValue<Double>(ref reader); break;
+				case "zfar": _zfar = DeserializePropertyValue<Double>(ref reader); break;
+				case "znear": _znear = DeserializePropertyValue<Double>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -667,7 +667,7 @@ namespace SharpGLTF.Schema2
 		private Double _znear;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "aspectRatio", _aspectRatio);
@@ -676,15 +676,15 @@ namespace SharpGLTF.Schema2
 			SerializeProperty(writer, "znear", _znear);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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(jsonPropertyName, reader); break;
+				case "aspectRatio": _aspectRatio = DeserializePropertyValue<Double?>(ref reader); break;
+				case "yfov": _yfov = DeserializePropertyValue<Double>(ref reader); break;
+				case "zfar": _zfar = DeserializePropertyValue<Double?>(ref reader); break;
+				case "znear": _znear = DeserializePropertyValue<Double>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -704,7 +704,7 @@ namespace SharpGLTF.Schema2
 		private CameraType _type;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializePropertyObject(writer, "orthographic", _orthographic);
@@ -712,14 +712,14 @@ namespace SharpGLTF.Schema2
 			SerializePropertyEnumSymbol<CameraType>(writer, "type", _type);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "orthographic": _orthographic = DeserializePropertyValue<CameraOrthographic>(reader); break;
-				case "perspective": _perspective = DeserializePropertyValue<CameraPerspective>(reader); break;
-				case "type": _type = DeserializePropertyValue<CameraType>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "orthographic": _orthographic = DeserializePropertyValue<CameraOrthographic>(ref reader); break;
+				case "perspective": _perspective = DeserializePropertyValue<CameraPerspective>(ref reader); break;
+				case "type": _type = DeserializePropertyValue<CameraType>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -738,20 +738,20 @@ namespace SharpGLTF.Schema2
 		private Int32? _texCoord = _texCoordDefault;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "index", _index);
 			SerializeProperty(writer, "texCoord", _texCoord, _texCoordDefault);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "index": _index = DeserializePropertyValue<Int32>(reader); break;
-				case "texCoord": _texCoord = DeserializePropertyValue<Int32?>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "index": _index = DeserializePropertyValue<Int32>(ref reader); break;
+				case "texCoord": _texCoord = DeserializePropertyValue<Int32?>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -781,7 +781,7 @@ namespace SharpGLTF.Schema2
 		private Double? _roughnessFactor = _roughnessFactorDefault;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "baseColorFactor", _baseColorFactor, _baseColorFactorDefault);
@@ -791,16 +791,16 @@ namespace SharpGLTF.Schema2
 			SerializeProperty(writer, "roughnessFactor", _roughnessFactor, _roughnessFactorDefault);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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(jsonPropertyName, reader); break;
+				case "baseColorFactor": _baseColorFactor = DeserializePropertyValue<Vector4?>(ref reader); break;
+				case "baseColorTexture": _baseColorTexture = DeserializePropertyValue<TextureInfo>(ref reader); break;
+				case "metallicFactor": _metallicFactor = DeserializePropertyValue<Double?>(ref reader); break;
+				case "metallicRoughnessTexture": _metallicRoughnessTexture = DeserializePropertyValue<TextureInfo>(ref reader); break;
+				case "roughnessFactor": _roughnessFactor = DeserializePropertyValue<Double?>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -813,18 +813,18 @@ namespace SharpGLTF.Schema2
 		private Double? _scale = _scaleDefault;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "scale", _scale, _scaleDefault);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "scale": _scale = DeserializePropertyValue<Double?>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "scale": _scale = DeserializePropertyValue<Double?>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -839,18 +839,18 @@ namespace SharpGLTF.Schema2
 		private Double? _strength = _strengthDefault;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "strength", _strength, _strengthDefault);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "strength": _strength = DeserializePropertyValue<Double?>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "strength": _strength = DeserializePropertyValue<Double?>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -884,7 +884,7 @@ namespace SharpGLTF.Schema2
 		private MaterialPBRMetallicRoughness _pbrMetallicRoughness;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "alphaCutoff", _alphaCutoff, _alphaCutoffDefault);
@@ -897,19 +897,19 @@ namespace SharpGLTF.Schema2
 			SerializePropertyObject(writer, "pbrMetallicRoughness", _pbrMetallicRoughness);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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(jsonPropertyName, reader); break;
+				case "alphaCutoff": _alphaCutoff = DeserializePropertyValue<Double?>(ref reader); break;
+				case "alphaMode": _alphaMode = DeserializePropertyValue<AlphaMode>(ref reader); break;
+				case "doubleSided": _doubleSided = DeserializePropertyValue<Boolean?>(ref reader); break;
+				case "emissiveFactor": _emissiveFactor = DeserializePropertyValue<Vector3?>(ref reader); break;
+				case "emissiveTexture": _emissiveTexture = DeserializePropertyValue<TextureInfo>(ref reader); break;
+				case "normalTexture": _normalTexture = DeserializePropertyValue<MaterialNormalTextureInfo>(ref reader); break;
+				case "occlusionTexture": _occlusionTexture = DeserializePropertyValue<MaterialOcclusionTextureInfo>(ref reader); break;
+				case "pbrMetallicRoughness": _pbrMetallicRoughness = DeserializePropertyValue<MaterialPBRMetallicRoughness>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -934,7 +934,7 @@ namespace SharpGLTF.Schema2
 		private List<Dictionary<String,Int32>> _targets;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "attributes", _attributes);
@@ -944,16 +944,16 @@ namespace SharpGLTF.Schema2
 			SerializeProperty(writer, "targets", _targets, _targetsMinItems);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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(jsonPropertyName, reader); break;
+				case "attributes": DeserializePropertyDictionary<Int32>(ref reader, _attributes); break;
+				case "indices": _indices = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "material": _material = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "mode": _mode = DeserializePropertyValue<PrimitiveType>(ref reader); break;
+				case "targets": DeserializePropertyList<Dictionary<String,Int32>>(ref reader, _targets); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -974,20 +974,20 @@ namespace SharpGLTF.Schema2
 		private List<Double> _weights;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "primitives", _primitives, _primitivesMinItems);
 			SerializeProperty(writer, "weights", _weights, _weightsMinItems);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "primitives": DeserializePropertyList<MeshPrimitive>(reader, _primitives); break;
-				case "weights": DeserializePropertyList<Double>(reader, _weights); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "primitives": DeserializePropertyList<MeshPrimitive>(ref reader, _primitives); break;
+				case "weights": DeserializePropertyList<Double>(ref reader, _weights); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -1022,7 +1022,7 @@ namespace SharpGLTF.Schema2
 		private List<Double> _weights;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "camera", _camera);
@@ -1036,20 +1036,20 @@ namespace SharpGLTF.Schema2
 			SerializeProperty(writer, "weights", _weights, _weightsMinItems);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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(jsonPropertyName, reader); break;
+				case "camera": _camera = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "children": DeserializePropertyList<Int32>(ref reader, _children); break;
+				case "matrix": _matrix = DeserializePropertyValue<Matrix4x4?>(ref reader); break;
+				case "mesh": _mesh = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "rotation": _rotation = DeserializePropertyValue<Quaternion?>(ref reader); break;
+				case "scale": _scale = DeserializePropertyValue<Vector3?>(ref reader); break;
+				case "skin": _skin = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "translation": _translation = DeserializePropertyValue<Vector3?>(ref reader); break;
+				case "weights": DeserializePropertyList<Double>(ref reader, _weights); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -1072,7 +1072,7 @@ namespace SharpGLTF.Schema2
 		private TextureWrapMode? _wrapT = _wrapTDefault;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializePropertyEnumValue<TextureInterpolationFilter>(writer, "magFilter", _magFilter);
@@ -1081,15 +1081,15 @@ namespace SharpGLTF.Schema2
 			SerializePropertyEnumValue<TextureWrapMode>(writer, "wrapT", _wrapT, _wrapTDefault);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "magFilter": _magFilter = DeserializePropertyValue<TextureInterpolationFilter>(reader); break;
-				case "minFilter": _minFilter = DeserializePropertyValue<TextureMipMapFilter>(reader); break;
-				case "wrapS": _wrapS = DeserializePropertyValue<TextureWrapMode>(reader); break;
-				case "wrapT": _wrapT = DeserializePropertyValue<TextureWrapMode>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "magFilter": _magFilter = DeserializePropertyValue<TextureInterpolationFilter>(ref reader); break;
+				case "minFilter": _minFilter = DeserializePropertyValue<TextureMipMapFilter>(ref reader); break;
+				case "wrapS": _wrapS = DeserializePropertyValue<TextureWrapMode>(ref reader); break;
+				case "wrapT": _wrapT = DeserializePropertyValue<TextureWrapMode>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -1105,18 +1105,18 @@ namespace SharpGLTF.Schema2
 		private List<Int32> _nodes;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "nodes", _nodes, _nodesMinItems);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "nodes": DeserializePropertyList<Int32>(reader, _nodes); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "nodes": DeserializePropertyList<Int32>(ref reader, _nodes); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -1136,7 +1136,7 @@ namespace SharpGLTF.Schema2
 		private Int32? _skeleton;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "inverseBindMatrices", _inverseBindMatrices);
@@ -1144,14 +1144,14 @@ namespace SharpGLTF.Schema2
 			SerializeProperty(writer, "skeleton", _skeleton);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "inverseBindMatrices": _inverseBindMatrices = DeserializePropertyValue<Int32?>(reader); break;
-				case "joints": DeserializePropertyList<Int32>(reader, _joints); break;
-				case "skeleton": _skeleton = DeserializePropertyValue<Int32?>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "inverseBindMatrices": _inverseBindMatrices = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "joints": DeserializePropertyList<Int32>(ref reader, _joints); break;
+				case "skeleton": _skeleton = DeserializePropertyValue<Int32?>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -1168,20 +1168,20 @@ namespace SharpGLTF.Schema2
 		private Int32? _source;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "sampler", _sampler);
 			SerializeProperty(writer, "source", _source);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "sampler": _sampler = DeserializePropertyValue<Int32?>(reader); break;
-				case "source": _source = DeserializePropertyValue<Int32?>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "sampler": _sampler = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "source": _source = DeserializePropertyValue<Int32?>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -1243,7 +1243,7 @@ namespace SharpGLTF.Schema2
 		private ChildrenCollection<Texture,ModelRoot> _textures;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializePropertyObject(writer, "asset", _asset);
@@ -1265,28 +1265,28 @@ namespace SharpGLTF.Schema2
 			SerializeProperty(writer, "textures", _textures, _texturesMinItems);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				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<TextureSampler>(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(jsonPropertyName, reader); break;
+				case "asset": _asset = DeserializePropertyValue<Asset>(ref reader); break;
+				case "extensionsRequired": DeserializePropertyList<String>(ref reader, _extensionsRequired); break;
+				case "extensionsUsed": DeserializePropertyList<String>(ref reader, _extensionsUsed); break;
+				case "accessors": DeserializePropertyList<Accessor>(ref reader, _accessors); break;
+				case "animations": DeserializePropertyList<Animation>(ref reader, _animations); break;
+				case "bufferViews": DeserializePropertyList<BufferView>(ref reader, _bufferViews); break;
+				case "buffers": DeserializePropertyList<Buffer>(ref reader, _buffers); break;
+				case "cameras": DeserializePropertyList<Camera>(ref reader, _cameras); break;
+				case "images": DeserializePropertyList<Image>(ref reader, _images); break;
+				case "materials": DeserializePropertyList<Material>(ref reader, _materials); break;
+				case "meshes": DeserializePropertyList<Mesh>(ref reader, _meshes); break;
+				case "nodes": DeserializePropertyList<Node>(ref reader, _nodes); break;
+				case "samplers": DeserializePropertyList<TextureSampler>(ref reader, _samplers); break;
+				case "scene": _scene = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "scenes": DeserializePropertyList<Scene>(ref reader, _scenes); break;
+				case "skins": DeserializePropertyList<Skin>(ref reader, _skins); break;
+				case "textures": DeserializePropertyList<Texture>(ref reader, _textures); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	
@@ -1305,7 +1305,7 @@ namespace SharpGLTF.Schema2
 		private String _uri;
 		
 	
-		protected override void SerializeProperties(JsonWriter writer)
+		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "bufferView", _bufferView);
@@ -1313,14 +1313,14 @@ namespace SharpGLTF.Schema2
 			SerializeProperty(writer, "uri", _uri);
 		}
 	
-		protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
 		{
 			switch (jsonPropertyName)
 			{
-				case "bufferView": _bufferView = DeserializePropertyValue<Int32?>(reader); break;
-				case "mimeType": _mimeType = DeserializePropertyValue<String>(reader); break;
-				case "uri": _uri = DeserializePropertyValue<String>(reader); break;
-				default: base.DeserializeProperty(jsonPropertyName, reader); break;
+				case "bufferView": _bufferView = DeserializePropertyValue<Int32?>(ref reader); break;
+				case "mimeType": _mimeType = DeserializePropertyValue<String>(ref reader); break;
+				case "uri": _uri = DeserializePropertyValue<String>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
 			}
 		}
 	

+ 1 - 1
src/SharpGLTF.Core/Schema2/gltf.Buffer.cs

@@ -86,7 +86,7 @@ namespace SharpGLTF.Schema2
 
         /// <summary>
         /// Called by the serializer immediatelly after
-        /// calling <see cref="_WriteToSatellite(WriteContext, string)"/>
+        /// calling <see cref="_WriteToSatellite(IO.WriteContext, string)"/>
         /// or <see cref="_WriteToInternal"/>
         /// </summary>
         internal void _ClearAfterWrite()

+ 13 - 11
src/SharpGLTF.Core/Schema2/gltf.ExtraProperties.cs

@@ -2,10 +2,13 @@
 using System.Collections.Generic;
 using System.Linq;
 
-using Newtonsoft.Json;
+// using Newtonsoft.Json;
+using System.Text.Json;
 
 using SharpGLTF.IO;
 
+using JsonToken = System.Text.Json.JsonTokenType;
+
 namespace SharpGLTF.Schema2
 {
     public abstract class ExtraProperties : JsonSerializable
@@ -147,10 +150,10 @@ namespace SharpGLTF.Schema2
         #region serialization API
 
         /// <summary>
-        /// Writes the properties of the current instance to a <see cref="JsonWriter"/>.
+        /// Writes the properties of the current instance to a <see cref="Utf8JsonWriter"/>.
         /// </summary>
         /// <param name="writer">The target writer.</param>
-        protected override void SerializeProperties(JsonWriter writer)
+        protected override void SerializeProperties(Utf8JsonWriter writer)
         {
             if (_extensions.Count > 0)
             {
@@ -191,26 +194,25 @@ namespace SharpGLTF.Schema2
         }
 
         /// <summary>
-        /// Reads the properties of the current instance from a <see cref="JsonReader"/>.
+        /// Reads the properties of the current instance from a <see cref="Utf8JsonReader"/>.
         /// </summary>
         /// <param name="property">The name of the property.</param>
         /// <param name="reader">The source reader.</param>
-        protected override void DeserializeProperty(string property, JsonReader reader)
+        protected override void DeserializeProperty(string property, ref Utf8JsonReader reader)
         {
             Guard.NotNullOrEmpty(property, nameof(property));
-            Guard.NotNull(reader, nameof(reader));
 
             switch (property)
             {
-                case "extensions": _DeserializeExtensions(this, reader, _extensions); break;
+                case "extensions": _DeserializeExtensions(this, ref reader, _extensions); break;
 
-                case "extras": _extras = DeserializeUnknownObject(reader); break;
+                case "extras": _extras = DeserializeUnknownObject(ref reader); break;
 
                 default: reader.Skip(); break;
             }
         }
 
-        private static void _DeserializeExtensions(JsonSerializable parent, JsonReader reader, IList<JsonSerializable> extensions)
+        private static void _DeserializeExtensions(JsonSerializable parent, ref Utf8JsonReader reader, IList<JsonSerializable> extensions)
         {
             reader.Read();
 
@@ -218,13 +220,13 @@ namespace SharpGLTF.Schema2
             {
                 while (reader.Read() && reader.TokenType != JsonToken.EndObject)
                 {
-                    var key = reader.Value as String;
+                    var key = reader.GetString();
 
                     var val = ExtensionsFactory.Create(parent, key);
 
                     if (val == null) val = new UnknownNode(key);
 
-                    val.Deserialize(reader);
+                    val.Deserialize(ref reader);
                     extensions.Add(val);
                     continue;
                 }

+ 1 - 1
src/SharpGLTF.Core/Schema2/gltf.Images.cs

@@ -343,7 +343,7 @@ namespace SharpGLTF.Schema2
 
         /// <summary>
         /// Called by the serializer immediatelly after
-        /// calling <see cref="_WriteToSatellite(FileWriterCallback, string)"/>
+        /// calling <see cref="_WriteToSatellite(IO.WriteContext, string)"/>
         /// or <see cref="_WriteToInternal"/>
         /// </summary>
         internal void _ClearAfterWrite()

+ 30 - 19
src/SharpGLTF.Core/Schema2/gltf.Serialization.Read.cs

@@ -4,14 +4,13 @@ using System.IO;
 using System.Linq;
 using System.Text;
 
-using Newtonsoft.Json;
-
 using BYTES = System.ArraySegment<byte>;
 
+using VALIDATIONMODE = SharpGLTF.Validation.ValidationMode;
+
 namespace SharpGLTF.Schema2
 {
     using MODEL = ModelRoot;
-    using VALIDATIONMODE = Validation.ValidationMode;
 
     public delegate Boolean ImageReaderCallback(Image image);
 
@@ -149,36 +148,48 @@ namespace SharpGLTF.Schema2
         {
             Guard.FilePathMustExist(filePath, nameof(filePath));
 
-            var context = IO.ReadContext.CreateFromFile(filePath);
-
-            string json = null;
+            BYTES json = default;
 
             using (var s = File.OpenRead(filePath))
             {
-                json = context.ReadJson(s);
+                json = IO.ReadContext.ReadJsonBytes(s);
             }
 
             return ParseSatellitePaths(json);
         }
 
-        private static string[] ParseSatellitePaths(string json)
+        private static string[] ParseSatellitePaths(BYTES json)
         {
-            var rss = Newtonsoft.Json.Linq.JObject.Parse(json);
+            var uris = new HashSet<string>();
 
-            var buffers = rss["buffers"]?.Select(item => (String)item["uri"]);
-            var images = rss["images"]?.Select(item => (String)item["uri"]);
+            void _addUri(System.Text.Json.JsonElement property)
+            {
+                var newUri = property.GetString();
 
-            IEnumerable<string> uris = buffers;
+                if (string.IsNullOrWhiteSpace(newUri)) return;
+                if (newUri.StartsWith("data:", StringComparison.OrdinalIgnoreCase)) return;
 
-            if (images != null)
-            {
-                uris = uris == null ? images : uris.Concat(images);
+                uris.Add(newUri);
             }
 
-            uris = uris
-                .Where(uri => !string.IsNullOrWhiteSpace(uri))
-                .Where(uri => !uri.StartsWith("data:", StringComparison.Ordinal))
-                .Distinct();
+            using (var dom = System.Text.Json.JsonDocument.Parse(json))
+            {
+                if (dom.RootElement.TryGetProperty("buffers", out System.Text.Json.JsonElement buffers))
+                {
+                    foreach (var buffer in buffers.EnumerateArray())
+                    {
+                        if (buffer.TryGetProperty("uri", out System.Text.Json.JsonElement uri)) _addUri(uri);
+                    }
+                }
+
+                if (dom.RootElement.TryGetProperty("images", out System.Text.Json.JsonElement images))
+                {
+                    foreach (var image in images.EnumerateArray())
+                    {
+                        if (image.TryGetProperty("uri", out System.Text.Json.JsonElement uri)) _addUri(uri);
+                    }
+                }
+            }
 
             return uris.ToArray();
         }

+ 24 - 19
src/SharpGLTF.Core/Schema2/gltf.Serialization.Write.cs

@@ -4,8 +4,6 @@ using System.IO;
 using System.Linq;
 using System.Text;
 
-using Newtonsoft.Json;
-
 using BYTES = System.ArraySegment<byte>;
 
 namespace SharpGLTF.Schema2
@@ -42,14 +40,6 @@ namespace SharpGLTF.Schema2
     {
         #region lifecycle
 
-        public static implicit operator WriteSettings(Formatting jsonfmt)
-        {
-            return new WriteSettings
-            {
-                JsonFormatting = jsonfmt
-            };
-        }
-
         public WriteSettings() { }
 
         public WriteSettings(WriteSettings other)
@@ -75,7 +65,7 @@ namespace SharpGLTF.Schema2
         /// <summary>
         /// Gets or sets a value indicating how to format the JSON document of the glTF.
         /// </summary>
-        public Formatting JsonFormatting { get; set; } = Formatting.None;
+        public Boolean JsonIndented { get; set; } = false;
 
         #endregion
 
@@ -86,7 +76,7 @@ namespace SharpGLTF.Schema2
             Guard.NotNull(other, nameof(other));
             this.ImageWriting = other.ImageWriting;
             this.MergeBuffers = other.MergeBuffers;
-            this.JsonFormatting = other.JsonFormatting;
+            this.JsonIndented = other.JsonIndented;
         }
 
         #endregion
@@ -158,15 +148,28 @@ namespace SharpGLTF.Schema2
         /// <summary>
         /// Gets the JSON document of this <see cref="MODEL"/>.
         /// </summary>
-        /// <param name="fmt">The formatting of the JSON document.</param>
+        /// <param name="indented">The formatting of the JSON document.</param>
         /// <returns>A JSON content.</returns>
-        public string GetJSON(Formatting fmt)
+        public string GetJSON(bool indented)
         {
+            using (var mm = new System.IO.MemoryStream())
+            {
+                _WriteJSON(mm, indented);
+
+                mm.Position = 0;
+
+                using (var ss = new System.IO.StreamReader(mm))
+                {
+                    return ss.ReadToEnd();
+                }
+            }
+
+            /*
             using (var ss = new StringWriter())
             {
                 _WriteJSON(ss, fmt);
                 return ss.ToString();
-            }
+            }*/
         }
 
         /// <summary>
@@ -210,12 +213,14 @@ namespace SharpGLTF.Schema2
 
         #region core
 
-        internal void _WriteJSON(TextWriter sw, Formatting fmt)
+        internal void _WriteJSON(System.IO.Stream sw, bool indented)
         {
-            using (var writer = new JsonTextWriter(sw))
-            {
-                writer.Formatting = fmt;
+            System.Text.Json.JsonWriterOptions options = default;
 
+            options.Indented = indented;
+
+            using (var writer = new System.Text.Json.Utf8JsonWriter(sw, options))
+            {
                 this.Serialize(writer);
             }
         }

+ 2 - 2
src/SharpGLTF.Core/SharpGLTF.Core.csproj

@@ -23,9 +23,9 @@
     </AssemblyAttribute>    
   </ItemGroup>  
   
-  <ItemGroup>    
-    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
+  <ItemGroup>        
     <PackageReference Include="System.Memory" Version="4.5.3" />
+    <PackageReference Include="System.Text.Json" Version="4.7.0" />
   </ItemGroup>
 
   <ItemGroup>

+ 1 - 1
src/SharpGLTF.Core/Validation/ModelException.cs

@@ -58,7 +58,7 @@ namespace SharpGLTF.Validation
         internal SchemaException(TARGET target, String message)
             : base(target, message) { }
 
-        internal SchemaException(TARGET target, Newtonsoft.Json.JsonReaderException rex)
+        internal SchemaException(TARGET target, System.Text.Json.JsonException rex)
             : base(target, rex) { }
     }
 

+ 1 - 1
src/SharpGLTF.Core/Validation/ValidationContext.cs

@@ -168,7 +168,7 @@ namespace SharpGLTF.Validation
 
         public void CheckSchemaIsJsonSerializable(ValueLocation location, Object value)
         {
-            if (IO.JsonUtils.IsSerializable(value)) return;
+            if (IO.JsonUtils.IsJsonSerializable(value)) return;
 
             AddSchemaError(location, "Invalid JSON data.");
         }

+ 2 - 5
src/SharpGLTF.Toolkit/IO/Zip.cs

@@ -50,7 +50,7 @@ namespace SharpGLTF.IO
         {
             return _Archive
                 .Entries
-                .Where(item => item.FullName.ToLower().EndsWith(".gltf") || item.FullName.ToLower().EndsWith(".glb"))
+                .Where(item => item.FullName.EndsWith(".gltf", StringComparison.OrdinalIgnoreCase) || item.FullName.EndsWith(".glb", StringComparison.OrdinalIgnoreCase))
                 .OrderBy(item => item.FullName);
         }
 
@@ -93,14 +93,11 @@ namespace SharpGLTF.IO
                     else return new ArraySegment<byte>(m.ToArray());
                 }
             }
-
         }
 
         private System.IO.Compression.ZipArchiveEntry _FindEntry(string filePath)
         {
-            filePath = filePath.ToLower();
-
-            var entry = _Archive.Entries.FirstOrDefault(item => item.FullName.ToLower() == filePath);
+            var entry = _Archive.Entries.FirstOrDefault(item => item.FullName.Equals(filePath, StringComparison.OrdinalIgnoreCase) );
             if (entry == null) throw new System.IO.FileNotFoundException(filePath);
             return entry;
         }

+ 3 - 1
tests/SharpGLTF.Tests/Collections/ChildrenCollectionTests.cs

@@ -23,8 +23,10 @@ namespace SharpGLTF.Collections
         [Test]
         public void TestChildCollectionList1()
         {
-            var list = new ChildrenCollection<TestChild, ChildrenCollectionTests>(this);
+            if (System.Diagnostics.Debugger.IsAttached) return;
 
+            var list = new ChildrenCollection<TestChild, ChildrenCollectionTests>(this);
+            
             Assert.Throws<ArgumentNullException>(() => list.Add(null));
 
             var item = new TestChild();

+ 1 - 1
tests/SharpGLTF.Tests/Schema2/Authoring/BasicSceneCreationTests.cs

@@ -44,7 +44,7 @@ namespace SharpGLTF.Schema2.Authoring
                 ["D"] = new IO.JsonDictionary { ["S"]= 1, ["T"] = 2 }
             };
 
-            var json = root.GetJSON(Newtonsoft.Json.Formatting.Indented);
+            var json = root.GetJSON(true);
 
             var bytes = root.WriteGLB();
             var rootBis = ModelRoot.ParseGLB(bytes);

+ 2 - 2
tests/SharpGLTF.Tests/Schema2/LoadAndSave/LoadSpecialModelsTest.cs

@@ -113,8 +113,8 @@ namespace SharpGLTF.Schema2.LoadAndSave
             // which is causing some problems to the interpolator.
 
             TestContext.CurrentContext.AttachShowDirLink();
-
-            var path = "Assets\\SpecialCases\\mouse.glb";
+            
+            var path = System.IO.Path.Combine(TestContext.CurrentContext.TestDirectory, "Assets\\SpecialCases\\mouse.glb");
 
             var model = ModelRoot.Load(path);
 

+ 3 - 2
tests/SharpGLTF.Tests/SharpGLTF.Tests.csproj

@@ -1,13 +1,13 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>netcoreapp2.2;net471</TargetFrameworks>
+    <TargetFrameworks>netcoreapp3.0;net471</TargetFrameworks>
 
     <IsPackable>false</IsPackable>
 
     <RootNamespace>SharpGLTF</RootNamespace>
 
-    <LangVersion>7.1</LangVersion>
+    <LangVersion>latest</LangVersion>
   </PropertyGroup>
 
   <ItemGroup>
@@ -21,6 +21,7 @@
   </ItemGroup>
 
   <ItemGroup>    
+    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />    
     <PackageReference Include="nunit" Version="3.12.0" />
     <PackageReference Include="NUnit3TestAdapter" Version="3.16.0">
       <PrivateAssets>all</PrivateAssets>

+ 1 - 1
tests/SharpGLTF.Tests/Utils.cs

@@ -124,7 +124,7 @@ namespace SharpGLTF
             }
             else if (fileName.ToLower().EndsWith(".gltf"))
             {
-                model.Save(fileName, Newtonsoft.Json.Formatting.Indented);
+                model.Save(fileName, new Schema2.WriteSettings { JsonIndented=true } );
             }
             else if (fileName.ToLower().EndsWith(".obj"))
             {