Browse Source

Added support to control json encoding when writing models.

Vicente Penades 4 years ago
parent
commit
05d0a5fe63

+ 1 - 1
src/SharpGLTF.Core/Schema2/Serialization.WriteContext.cs

@@ -195,7 +195,7 @@ namespace SharpGLTF.Schema2
 
             using (var m = new MemoryStream())
             {
-                model._WriteJSON(m, this.JsonIndented);
+                model._WriteJSON(m, this.JsonOptions);
 
                 WriteAllBytesToEnd($"{baseName}.gltf", m.ToArraySegment());
             }

+ 33 - 8
src/SharpGLTF.Core/Schema2/Serialization.WriteSettings.cs

@@ -58,6 +58,12 @@ namespace SharpGLTF.Schema2
 
         #endregion
 
+        #region data
+
+        private System.Text.Json.JsonWriterOptions _JsonOptions = default;
+
+        #endregion
+
         #region properties
 
         /// <summary>
@@ -78,7 +84,20 @@ namespace SharpGLTF.Schema2
         /// <summary>
         /// Gets or sets a value indicating whether the JSON formatting will include indentation.
         /// </summary>
-        public Boolean JsonIndented { get; set; }
+        public Boolean JsonIndented
+        {
+            get => _JsonOptions.Indented;
+            set => _JsonOptions.Indented = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating the Json options to be used for writing.
+        /// </summary>
+        public System.Text.Json.JsonWriterOptions JsonOptions
+        {
+            get => _JsonOptions;
+            set => _JsonOptions = value;
+        }
 
         /// <summary>
         /// Gets or sets a value indicating the level of validation applied when loading a file.
@@ -96,7 +115,7 @@ namespace SharpGLTF.Schema2
             other.ImageWriting = this.ImageWriting;
             other.ImageWriteCallback = this.ImageWriteCallback;
             other.MergeBuffers = this.MergeBuffers;
-            other.JsonIndented = this.JsonIndented;
+            other._JsonOptions = this._JsonOptions;
             other.Validation = this.Validation;
         }
 
@@ -170,10 +189,20 @@ namespace SharpGLTF.Schema2
         /// <param name="indented">The formatting of the JSON document.</param>
         /// <returns>A JSON content.</returns>
         public string GetJSON(bool indented)
+        {
+            var options = new System.Text.Json.JsonWriterOptions
+            {
+                Indented = indented
+            };
+
+            return GetJSON(options);
+        }
+
+        public string GetJSON(System.Text.Json.JsonWriterOptions options)
         {
             using (var mm = new System.IO.MemoryStream())
             {
-                _WriteJSON(mm, indented);
+                _WriteJSON(mm, options);
 
                 mm.Position = 0;
 
@@ -227,12 +256,8 @@ namespace SharpGLTF.Schema2
 
         #region core
 
-        internal void _WriteJSON(System.IO.Stream sw, bool indented)
+        internal void _WriteJSON(System.IO.Stream sw, System.Text.Json.JsonWriterOptions options)
         {
-            System.Text.Json.JsonWriterOptions options = default;
-
-            options.Indented = indented;
-
             using (var writer = new System.Text.Json.Utf8JsonWriter(sw, options))
             {
                 this.Serialize(writer);

BIN
tests/Assets/extended 你好 characters.jpg


+ 52 - 0
tests/SharpGLTF.Core.Tests/IO/JsonContentTests.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using System.Text.Encodings.Web;
 
 using NUnit.Framework;
 
@@ -197,6 +198,57 @@ namespace SharpGLTF.IO
 
     }
 
+    [Category("Core.IO")]
+    public class JsonSerializationTests
+    {
+        const string UNESCAPED = "你好";
+        const string ESCAPED = "\u4f60\u597d";
+
+        [Test]
+        public void TestJsonExtendedCharacters()
+        {
+            TestContext.CurrentContext.AttachShowDirLink();
+            TestContext.CurrentContext.AttachGltfValidatorLinks();
+
+            // create a test model
+
+            var model = Schema2.ModelRoot.CreateModel();
+
+            model.Asset.Copyright = UNESCAPED;
+            model.UseScene(UNESCAPED);
+            model.Asset.Extras = JsonContent.CreateFrom(new string[] { UNESCAPED, ESCAPED, UNESCAPED });
+            model.CreateImage().Content = Memory.MemoryImage.DefaultPngImage;
+
+            // create write settings
+
+            var joptions = new System.Text.Json.JsonWriterOptions
+            {
+                Indented = true,
+                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
+            };
+
+            var wsettings = new Schema2.WriteSettings();
+            wsettings.JsonOptions = joptions;
+
+            // model save-load roundtrip
+
+            var roundtripPath = model.AttachToCurrentTest("extended 你好 characters.gltf", wsettings);
+            var roundtripJson = System.IO.File.ReadAllText(roundtripPath);
+            var roundtripModel = Schema2.ModelRoot.Load(roundtripPath);
+
+            // checks
+
+            TestContext.WriteLine(roundtripJson);
+
+            Assert.IsTrue(roundtripJson.Contains("你好"));
+            
+            // https://github.com/KhronosGroup/glTF/issues/1978#issuecomment-831744624
+            Assert.IsTrue(roundtripJson.Contains("extended%20%E4%BD%A0%E5%A5%BD%20characters.png"));
+
+            Assert.IsTrue(roundtripModel.LogicalImages[0].Content.IsPng);
+        }
+    }
+
     [Category("Core.IO")]
     public class ContextTests
     {