diff --git a/Src/Newtonsoft.Json.Tests/Converters/BinaryConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/BinaryConverterTests.cs index 1af3384d..94ca068e 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/BinaryConverterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/BinaryConverterTests.cs @@ -39,6 +39,20 @@ namespace Newtonsoft.Json.Tests.Converters Assert.AreEqual(null, binaryClass.NullBinary); } + [Test] + public void DeserializeBinaryClassFromJsonArray() + { + string json = @"{ + ""Binary"": [0, 1, 2, 3], + ""NullBinary"": null +}"; + + BinaryClass binaryClass = JsonConvert.DeserializeObject(json, new BinaryConverter()); + + Assert.AreEqual(new byte[] { 0, 1, 2, 3 }, binaryClass.Binary.ToArray()); + Assert.AreEqual(null, binaryClass.NullBinary); + } + public class BinaryClass { public Binary Binary { get; set; } @@ -132,5 +146,18 @@ namespace Newtonsoft.Json.Tests.Converters Assert.AreEqual(null, byteArrayClass.NullByteArray); } + [Test] + public void DeserializeByteArrayFromJsonArray() + { + string json = @"{ + ""ByteArray"": [0, 1, 2, 3], + ""NullByteArray"": null +}"; + + ByteArrayClass c = JsonConvert.DeserializeObject(json); + Assert.IsNotNull(c.ByteArray); + Assert.AreEqual(4, c.ByteArray.Length); + Assert.AreEqual(new byte[] { 0, 1, 2, 3 }, c.ByteArray); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Converters/BinaryConverter.cs b/Src/Newtonsoft.Json/Converters/BinaryConverter.cs index c92c6f7c..361c622b 100644 --- a/Src/Newtonsoft.Json/Converters/BinaryConverter.cs +++ b/Src/Newtonsoft.Json/Converters/BinaryConverter.cs @@ -29,6 +29,7 @@ using System.Data.SqlTypes; #endif using System.Globalization; using Newtonsoft.Json.Utilities; +using System.Collections.Generic; namespace Newtonsoft.Json.Converters { @@ -105,14 +106,25 @@ namespace Newtonsoft.Json.Converters return null; } - if (reader.TokenType != JsonToken.String) - throw new Exception("Unexpected token parsing binary. Expected String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); + byte[] data; - // current token is already at base64 string - // unable to call ReadAsBytes so do it the old fashion way - string encodedData = reader.Value.ToString(); - byte[] data = Convert.FromBase64String(encodedData); + if (reader.TokenType == JsonToken.StartArray) + { + data = ReadByteArray(reader); + } + else if (reader.TokenType == JsonToken.String) + { + // current token is already at base64 string + // unable to call ReadAsBytes so do it the old fashion way + string encodedData = reader.Value.ToString(); + data = Convert.FromBase64String(encodedData); + } + else + { + throw new Exception("Unexpected token parsing binary. Expected String or StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); + } + #if !SILVERLIGHT && !PocketPC && !NET20 if (t.AssignableToTypeName(BinaryTypeName)) return Activator.CreateInstance(t, data); @@ -124,6 +136,30 @@ namespace Newtonsoft.Json.Converters throw new Exception("Unexpected object type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, objectType)); } + private byte[] ReadByteArray(JsonReader reader) + { + List byteList = new List(); + + while (reader.Read()) + { + switch (reader.TokenType) + { + case JsonToken.Integer: + byteList.Add(Convert.ToByte(reader.Value, CultureInfo.InvariantCulture)); + break; + case JsonToken.EndArray: + return byteList.ToArray(); + case JsonToken.Comment: + // skip + break; + default: + throw new Exception("Unexpected token when reading bytes: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); + } + } + + throw new Exception("Unexpected end when reading bytes."); + } + /// /// Determines whether this instance can convert the specified object type. /// diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs index bb553a27..2dc235e8 100644 --- a/Src/Newtonsoft.Json/JsonTextReader.cs +++ b/Src/Newtonsoft.Json/JsonTextReader.cs @@ -333,16 +333,42 @@ 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 (TokenType == JsonToken.Null) return null; if (TokenType == JsonToken.Bytes) return (byte[]) Value; + if (TokenType == JsonToken.StartArray) + { + List data = new List(); + + while (ReadInternal()) + { + switch (TokenType) + { + case JsonToken.Integer: + data.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture)); + break; + case JsonToken.EndArray: + byte[] d = data.ToArray(); + SetToken(JsonToken.Bytes, d); + return d; + case JsonToken.Comment: + // skip + break; + default: + throw CreateJsonReaderException("Unexpected token when reading bytes: {0}. Line {1}, position {2}.", TokenType, _currentLineNumber, _currentLinePosition); + } + } + + throw CreateJsonReaderException("Unexpected end when reading bytes: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); + } + throw CreateJsonReaderException("Unexpected token when reading bytes: {0}. Line {1}, position {2}.", TokenType, _currentLineNumber, _currentLinePosition); }