diff --git a/Octokit.Tests/SimpleJsonSerializerTests.cs b/Octokit.Tests/SimpleJsonSerializerTests.cs index bd3a375b..bc1c0ad1 100644 --- a/Octokit.Tests/SimpleJsonSerializerTests.cs +++ b/Octokit.Tests/SimpleJsonSerializerTests.cs @@ -1,5 +1,7 @@ using Octokit.Helpers; using Octokit.Internal; +using System.Linq; +using System.Text; using Xunit; namespace Octokit.Tests @@ -64,6 +66,33 @@ namespace Octokit.Tests Assert.Equal("{\"int\":42,\"bool\":true}", json); } + [Fact] + public void HandleUnicodeCharacters() + { + const string backspace = "\b"; + const string tab = "\t"; + + var sb = new StringBuilder(); + sb.Append("My name has Unicode characters"); + Enumerable.Range(0, 19).Select(e => System.Convert.ToChar(e)) + .Aggregate(sb, (a, b) => a.Append(b)); + sb.Append(backspace).Append(tab); + var data = sb.ToString(); + + var json = new SimpleJsonSerializer().Serialize(data); + var lastTabCharacter = (json + .Reverse() + .Skip(1) + .Take(2) + .Reverse() + .Aggregate(new StringBuilder(),(a,b) =>a.Append(b))); + + var deserializeData = new SimpleJsonSerializer().Deserialize(json); + + Assert.True(lastTabCharacter.ToString().Equals("\\t")); + Assert.Equal(data,deserializeData ); + } + [Fact] public void HandlesBase64EncodedStrings() { diff --git a/Octokit/SimpleJson.cs b/Octokit/SimpleJson.cs index a9e57e7d..e743d627 100644 --- a/Octokit/SimpleJson.cs +++ b/Octokit/SimpleJson.cs @@ -517,7 +517,12 @@ namespace Octokit private const int BUILDER_CAPACITY = 2000; private static readonly char[] EscapeTable; - private static readonly char[] EscapeCharacters = new char[] { '"', '\\', '\b', '\f', '\n', '\r', '\t' }; + private static readonly char[] EscapeCharacters = new char[] { '"', '\\', + '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', + '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', + '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', + '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f' + }; private static readonly string EscapeCharactersString = new string(EscapeCharacters); static SimpleJson() @@ -1114,11 +1119,7 @@ namespace Octokit // Non ascii characters are fine, buffer them up and send them to the builder // in larger chunks if possible. The escape table is a 1:1 translation table // with \0 [default(char)] denoting a safe character. - if (c >= EscapeTable.Length || EscapeTable[c] == default(char)) - { - safeCharacterCount++; - } - else + if (Char.IsControl(c) || c == '\"' || c == '\\') { if (safeCharacterCount > 0) { @@ -1127,7 +1128,37 @@ namespace Octokit } builder.Append('\\'); - builder.Append(EscapeTable[c]); + switch (c) + { + case '\\': + builder.Append('\\'); + break; + case '\"': + builder.Append('\"'); + break; + case '\b': + builder.Append('b'); + break; + case '\f': + builder.Append('f'); + break; + case '\r': + builder.Append('r'); + break; + case '\t': + builder.Append('t'); + break; + case '\n': + builder.Append('n'); + break; + default: + builder.AppendFormat("u{0:X4}", (int)c); + break; + } + } + else + { + safeCharacterCount++; } } diff --git a/SolutionInfo.cs b/SolutionInfo.cs index e2fd9c8e..ba2f342f 100644 --- a/SolutionInfo.cs +++ b/SolutionInfo.cs @@ -6,10 +6,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyVersionAttribute("0.17.0")] [assembly: AssemblyFileVersionAttribute("0.17.0")] [assembly: ComVisibleAttribute(false)] -namespace System -{ - internal static class AssemblyVersionInformation - { +namespace System { + internal static class AssemblyVersionInformation { internal const string Version = "0.17.0"; } }