diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs index 18e701cd..a4935aed 100644 --- a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs +++ b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs @@ -1214,5 +1214,34 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(c1.NullableTimeSpan, c2.NullableTimeSpan); Assert.AreEqual(c1.Uri, c2.Uri); } + + [Test] + public void DeserializeByteArrayWithTypeNameHandling() + { + TestObject test = new TestObject("Test", new byte[] { 72, 63, 62, 71, 92, 55 }); + + JsonSerializer serializer = new JsonSerializer(); + serializer.TypeNameHandling = TypeNameHandling.All; + + byte[] objectBytes; + using (MemoryStream bsonStream = new MemoryStream()) + using (JsonWriter bsonWriter = new BsonWriter(bsonStream)) + { + serializer.Serialize(bsonWriter, test); + bsonWriter.Flush(); + + objectBytes = bsonStream.ToArray(); + } + + using (MemoryStream bsonStream = new MemoryStream(objectBytes)) + using (JsonReader bsonReader = new BsonReader(bsonStream)) + { + // Get exception here + TestObject newObject = (TestObject)serializer.Deserialize(bsonReader); + + Assert.AreEqual("Test", newObject.Name); + Assert.AreEqual(new byte[] { 72, 63, 62, 71, 92, 55 }, newObject.Data); + } + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Linq/JTokenReaderTest.cs b/Src/Newtonsoft.Json.Tests/Linq/JTokenReaderTest.cs index a3e835c9..9a0df42c 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JTokenReaderTest.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JTokenReaderTest.cs @@ -30,6 +30,7 @@ using NUnit.Framework; using Newtonsoft.Json; using System.IO; using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Tests.Serialization; namespace Newtonsoft.Json.Tests.Linq { @@ -305,5 +306,30 @@ namespace Newtonsoft.Json.Tests.Linq ReadAsBytesTestObject x = s.Deserialize(new JTokenReader(nullToken)); Assert.IsNull(x.Data); } + + [Test] + public void DeserializeByteArrayWithTypeNameHandling() + { + TestObject test = new TestObject("Test", new byte[] { 72, 63, 62, 71, 92, 55 }); + + string json = JsonConvert.SerializeObject(test, Formatting.Indented, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.All + }); + + JObject o = JObject.Parse(json); + + JsonSerializer serializer = new JsonSerializer(); + serializer.TypeNameHandling = TypeNameHandling.All; + + using (JsonReader nodeReader = o.CreateReader()) + { + // Get exception here + TestObject newObject = (TestObject)serializer.Deserialize(nodeReader); + + Assert.AreEqual("Test", newObject.Name); + Assert.AreEqual(new byte[] { 72, 63, 62, 71, 92, 55 }, newObject.Data); + } + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index d3883b4a..13aae919 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -66,5 +66,5 @@ using System.Runtime.InteropServices; // by using the '*' as shown below: [assembly: AssemblyVersion("4.0.3.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.0.3.14301")] +[assembly: AssemblyFileVersion("4.0.3.14302")] #endif diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index c7386956..38ffce62 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -44,6 +44,7 @@ using System.Collections; using System.Xml; using System.Xml.Serialization; using System.Collections.ObjectModel; +using Newtonsoft.Json.Bson; using Newtonsoft.Json.Linq; using System.Linq; using Newtonsoft.Json.Converters; @@ -5015,6 +5016,52 @@ keyword such as type of business."" Assert.AreEqual(uri, output); } + + [Test] + public void DeserializeByteArrayWithTypeNameHandling() + { + TestObject test = new TestObject("Test", new byte[] { 72, 63, 62, 71, 92, 55 }); + + JsonSerializer serializer = new JsonSerializer(); + serializer.TypeNameHandling = TypeNameHandling.All; + + byte[] objectBytes; + using (MemoryStream bsonStream = new MemoryStream()) + using (JsonWriter bsonWriter = new JsonTextWriter(new StreamWriter(bsonStream))) + { + serializer.Serialize(bsonWriter, test); + bsonWriter.Flush(); + + objectBytes = bsonStream.ToArray(); + } + + using (MemoryStream bsonStream = new MemoryStream(objectBytes)) + using (JsonReader bsonReader = new JsonTextReader(new StreamReader(bsonStream))) + { + // Get exception here + TestObject newObject = (TestObject) serializer.Deserialize(bsonReader); + + Assert.AreEqual("Test", newObject.Name); + Assert.AreEqual(new byte[] { 72, 63, 62, 71, 92, 55 }, newObject.Data); + } + } + } + + public class TestObject + { + public TestObject() + { + + } + + public TestObject(string name, byte[] data) + { + Name = name; + Data = data; + } + + public string Name { get; set; } + public byte[] Data { get; set; } } public class UriGuidTimeSpanTestClass diff --git a/Src/Newtonsoft.Json/Bson/BsonReader.cs b/Src/Newtonsoft.Json/Bson/BsonReader.cs index 25d19d25..8f3b2de6 100644 --- a/Src/Newtonsoft.Json/Bson/BsonReader.cs +++ b/Src/Newtonsoft.Json/Bson/BsonReader.cs @@ -158,6 +158,14 @@ namespace Newtonsoft.Json.Bson { Read(); + if (IsWrappedInTypeObject()) + { + byte[] data = ReadAsBytes(); + Read(); + SetToken(JsonToken.Bytes, data); + return data; + } + if (TokenType == JsonToken.Null) return null; if (TokenType == JsonToken.Bytes) @@ -166,6 +174,30 @@ namespace Newtonsoft.Json.Bson throw new JsonReaderException("Error reading bytes. Expected bytes but got {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } + private bool IsWrappedInTypeObject() + { + if (TokenType == JsonToken.StartObject) + { + Read(); + if (Value.ToString() == "$type") + { + Read(); + if (Value != null && Value.ToString().StartsWith("System.Byte[]")) + { + Read(); + if (Value.ToString() == "$value") + { + return true; + } + } + } + + throw new JsonReaderException("Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); + } + + return false; + } + /// /// Reads the next JSON token from the stream as a . /// diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs index 2dc235e8..ba999a60 100644 --- a/Src/Newtonsoft.Json/JsonTextReader.cs +++ b/Src/Newtonsoft.Json/JsonTextReader.cs @@ -323,6 +323,35 @@ namespace Newtonsoft.Json return ReadInternal(); } + private bool IsWrappedInTypeObject() + { + _readType = ReadType.Read; + + if (TokenType == JsonToken.StartObject) + { + int startObjectLineNumber = _currentLineNumber; + int startObjectLinePosition = _currentLinePosition; + + ReadInternal(); + if (Value.ToString() == "$type") + { + ReadInternal(); + if (Value != null && Value.ToString().StartsWith("System.Byte[]")) + { + ReadInternal(); + if (Value.ToString() == "$value") + { + return true; + } + } + } + + throw CreateJsonReaderException("Unexpected token when reading bytes: {0}. Line {1}, position {2}.", JsonToken.StartObject, startObjectLineNumber, startObjectLinePosition); + } + + return false; + } + /// /// Reads the next JSON token from the stream as a . /// @@ -333,11 +362,19 @@ namespace Newtonsoft.Json { _readType = ReadType.ReadAsBytes; - do - { - if (!ReadInternal()) - throw CreateJsonReaderException("Unexpected end when reading bytes: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); - } while (TokenType == JsonToken.Comment); + do + { + if (!ReadInternal()) + throw CreateJsonReaderException("Unexpected end when reading bytes: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); + } while (TokenType == JsonToken.Comment); + + if (IsWrappedInTypeObject()) + { + byte[] data = ReadAsBytes(); + ReadInternal(); + SetToken(JsonToken.Bytes, data); + return data; + } if (TokenType == JsonToken.Null) return null; diff --git a/Src/Newtonsoft.Json/Linq/JTokenReader.cs b/Src/Newtonsoft.Json/Linq/JTokenReader.cs index b88495b5..8dc833ae 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenReader.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenReader.cs @@ -38,6 +38,14 @@ namespace Newtonsoft.Json.Linq { Read(); + if (IsWrappedInTypeObject()) + { + byte[] data = ReadAsBytes(); + Read(); + SetToken(JsonToken.Bytes, data); + return data; + } + // attempt to convert possible base 64 string to bytes if (TokenType == JsonToken.String) { @@ -54,6 +62,30 @@ namespace Newtonsoft.Json.Linq throw new JsonReaderException("Error reading bytes. Expected bytes but got {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } + private bool IsWrappedInTypeObject() + { + if (TokenType == JsonToken.StartObject) + { + Read(); + if (Value.ToString() == "$type") + { + Read(); + if (Value != null && Value.ToString().StartsWith("System.Byte[]")) + { + Read(); + if (Value.ToString() == "$value") + { + return true; + } + } + } + + throw new JsonReaderException("Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); + } + + return false; + } + /// /// Reads the next JSON token from the stream as a . /// diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 72dfcaa2..97643c93 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -85,7 +85,7 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.0.3.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.0.3.14301")] +[assembly: AssemblyFileVersion("4.0.3.14302")] #endif [assembly: CLSCompliant(true)]