Skip to content

Commit b8c7554

Browse files
committed
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.
1 parent 5763b32 commit b8c7554

31 files changed

+817
-671
lines changed

build/SharpGLTF.CodeGen/CodeGen/EmitCSharp.cs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System;
1+
// #define USENEWTONSOFT
2+
3+
using System;
24
using System.Collections.Generic;
35
using System.Linq;
46
using System.Reflection;
@@ -331,7 +333,12 @@ public string EmitContext(SchemaType.Context context)
331333
sb.AppendLine("using System.Linq;");
332334
sb.AppendLine("using System.Text;");
333335
sb.AppendLine("using System.Numerics;");
336+
337+
#if USENEWTONSOFT
334338
sb.AppendLine("using Newtonsoft.Json;");
339+
#else
340+
sb.AppendLine("using System.Text.Json;");
341+
#endif
335342
sb.AppendLine();
336343

337344
sb.AppendLine($"namespace {Constants.OutputNamespace}");
@@ -471,7 +478,7 @@ internal IEnumerable<string> _GetClassField(FieldInfo f)
471478
yield return string.Empty;
472479
}
473480

474-
#endregion
481+
#endregion
475482
}
476483

477484
/// <summary>
@@ -503,6 +510,8 @@ public CSharpClassEmitter(CSharpEmitter emitter)
503510

504511
public bool HasBaseClass { get; set; }
505512

513+
private const string _READERMODIFIER = "ref ";
514+
506515
#endregion
507516

508517
#region API
@@ -526,7 +535,7 @@ public void AddFields(ClassType type)
526535
this.AddFieldSerializerCase(smethod);
527536

528537
// emit deserializer
529-
this.AddFieldDeserializerCase(f.PersistentName, $"{frname} = DeserializePropertyValue<{_Emitter._GetRuntimeName(etype)}>(reader);");
538+
this.AddFieldDeserializerCase(f.PersistentName, $"{frname} = DeserializePropertyValue<{_Emitter._GetRuntimeName(etype)}>({_READERMODIFIER}reader);");
530539

531540
continue;
532541
}
@@ -565,15 +574,15 @@ private string _GetJSonDeserializerMethod(FieldInfo f)
565574
if (f.FieldType is ArrayType atype)
566575
{
567576
var titem = _Emitter._GetRuntimeName(atype.ItemType);
568-
return $"DeserializePropertyList<{titem}>(reader, {fname});";
577+
return $"DeserializePropertyList<{titem}>({_READERMODIFIER}reader, {fname});";
569578
}
570579
else if (f.FieldType is DictionaryType dtype)
571580
{
572581
var titem = _Emitter._GetRuntimeName(dtype.ValueType);
573-
return $"DeserializePropertyDictionary<{titem}>(reader, {fname});";
582+
return $"DeserializePropertyDictionary<{titem}>({_READERMODIFIER}reader, {fname});";
574583
}
575584

576-
return $"{fname} = DeserializePropertyValue<{_Emitter._GetRuntimeName(f.FieldType)}>(reader);";
585+
return $"{fname} = DeserializePropertyValue<{_Emitter._GetRuntimeName(f.FieldType)}>({_READERMODIFIER}reader);";
577586
}
578587

579588
public void AddFieldSerializerCase(string line) { _SerializerBody.Add(line); }
@@ -585,6 +594,15 @@ public void AddFieldDeserializerCase(string persistentName, string line)
585594

586595
public IEnumerable<string> EmitCode()
587596
{
597+
#if USENEWTONSOFT
598+
var readerType = "JsonReader";
599+
var writerType = "JsonWriter";
600+
#else
601+
var readerType = "ref Utf8JsonReader";
602+
var writerType = "Utf8JsonWriter";
603+
#endif
604+
605+
588606
foreach (var l in ClassSummary.EmitSummary(0)) yield return l;
589607

590608
yield return ClassDeclaration;
@@ -597,7 +615,7 @@ public IEnumerable<string> EmitCode()
597615
yield return string.Empty;
598616

599617
// yield return "/// <inheritdoc />".Indent(1);
600-
yield return "protected override void SerializeProperties(JsonWriter writer)".Indent(1);
618+
yield return $"protected override void SerializeProperties({writerType} writer)".Indent(1);
601619
yield return "{".Indent(1);
602620
if (HasBaseClass) yield return "base.SerializeProperties(writer);".Indent(2);
603621
foreach (var l in _SerializerBody.Indent(2)) yield return l;
@@ -606,13 +624,13 @@ public IEnumerable<string> EmitCode()
606624
yield return string.Empty;
607625

608626
// yield return "/// <inheritdoc />".Indent(1);
609-
yield return "protected override void DeserializeProperty(string jsonPropertyName, JsonReader reader)".Indent(1);
627+
yield return $"protected override void DeserializeProperty(string jsonPropertyName, {readerType} reader)".Indent(1);
610628
yield return "{".Indent(1);
611629
yield return "switch (jsonPropertyName)".Indent(2);
612630
yield return "{".Indent(2);
613631

614632
foreach (var l in _DeserializerSwitchBody.Indent(3)) yield return l;
615-
if (HasBaseClass) yield return "default: base.DeserializeProperty(jsonPropertyName, reader); break;".Indent(3);
633+
if (HasBaseClass) yield return $"default: base.DeserializeProperty(jsonPropertyName,{_READERMODIFIER}reader); break;".Indent(3);
616634
else yield return "default: throw new NotImplementedException();".Indent(3);
617635

618636
yield return "}".Indent(2);
@@ -623,6 +641,6 @@ public IEnumerable<string> EmitCode()
623641
yield return "}";
624642
}
625643

626-
#endregion
644+
#endregion
627645
}
628646
}

src/SharpGLTF.Core/IO/BinarySerialization.cs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,32 @@ static class BinarySerialization
2020

2121
#region read
2222

23+
public static bool IsBinaryHeader(Byte a, Byte b, Byte c, Byte d)
24+
{
25+
uint magic = 0;
26+
magic |= (uint)a;
27+
magic |= (uint)b << 8;
28+
magic |= (uint)c << 16;
29+
magic |= (uint)d << 24;
30+
31+
return magic == GLTFHEADER;
32+
}
33+
2334
internal static bool _Identify(Stream stream)
2435
{
2536
Guard.NotNull(stream, nameof(stream));
2637
Guard.IsTrue(stream.CanSeek, nameof(stream), "A seekable stream is required for glTF/GLB format identification");
2738

2839
var currPos = stream.Position;
2940

30-
uint magic = 0;
31-
magic |= (uint)stream.ReadByte();
32-
magic |= (uint)stream.ReadByte() << 8;
33-
magic |= (uint)stream.ReadByte() << 16;
34-
magic |= (uint)stream.ReadByte() << 24;
41+
var a = stream.ReadByte();
42+
var b = stream.ReadByte();
43+
var c = stream.ReadByte();
44+
var d = stream.ReadByte();
3545

3646
stream.Position = currPos; // restart read position
3747

38-
return magic == GLTFHEADER;
48+
return IsBinaryHeader((Byte)a, (Byte)b, (Byte)c, (Byte)d);
3949
}
4050

4151
public static IReadOnlyDictionary<UInt32, Byte[]> ReadBinaryFile(Stream stream)
@@ -132,7 +142,7 @@ public static void WriteBinaryModel(this BinaryWriter binaryWriter, ROOT model)
132142
{
133143
var ex = IsBinaryCompatible(model); if (ex != null) throw ex;
134144

135-
var jsonText = model.GetJSON(Newtonsoft.Json.Formatting.None);
145+
var jsonText = model.GetJSON(false);
136146
var jsonChunk = Encoding.UTF8.GetBytes(jsonText);
137147
var jsonPadding = jsonChunk.Length & 3; if (jsonPadding != 0) jsonPadding = 4 - jsonPadding;
138148

src/SharpGLTF.Core/IO/Json.cs renamed to src/SharpGLTF.Core/IO/JsonCollections.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,26 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Text;
5+
using System.Text.Json;
56

67
namespace SharpGLTF.IO
78
{
89
static class JsonUtils
910
{
10-
public static bool IsSerializable(Object value)
11+
public static ArraySegment<Byte> ReadBytesToEnd(this System.IO.Stream s)
12+
{
13+
using (var m = new System.IO.MemoryStream())
14+
{
15+
s.CopyTo(m);
16+
if (m.TryGetBuffer(out ArraySegment<Byte> segment)) return segment;
17+
18+
var array = m.ToArray();
19+
20+
return new ArraySegment<byte>(array);
21+
}
22+
}
23+
24+
public static bool IsJsonSerializable(Object value)
1125
{
1226
if (value == null) return false;
1327

@@ -23,12 +37,12 @@ public static bool IsSerializable(Object value)
2337

2438
if (value is JsonList list)
2539
{
26-
return list.All(item => IsSerializable(item));
40+
return list.All(item => IsJsonSerializable(item));
2741
}
2842

2943
if (value is JsonDictionary dict)
3044
{
31-
return dict.Values.All(item => IsSerializable(item));
45+
return dict.Values.All(item => IsJsonSerializable(item));
3246
}
3347

3448
return false;

0 commit comments

Comments
 (0)