Update
Fixed in changeset 70120ce , which will be included in Json.NET 8.0.2.
Original answer
Confirmed - this is apparently a regression. Consider the following simple test class:
internal class HasByteArray { public byte[] EncryptedPassword { get; set; } }
Now, if I try to get around the class using TypeNameHandling.Objects :
private static void TestSimple() { var test = new HasByteArray { EncryptedPassword = Convert.FromBase64String("cGFzc3dvcmQ=") }; try { TestRoundTrip(test); } catch (Exception ex) { Debug.WriteLine(ex); } } private static void TestRoundTrip<T>(T item) { var jsonSerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple }; TestRoundTrip<T>(item, jsonSerializerSettings); } private static void TestRoundTrip<T>(T item, JsonSerializerSettings jsonSerializerSettings) { var json = JsonConvert.SerializeObject(item, Formatting.Indented, jsonSerializerSettings); Debug.WriteLine(json); var item2 = JsonConvert.DeserializeObject<T>(json, jsonSerializerSettings); var json2 = JsonConvert.SerializeObject(item2, Formatting.Indented, jsonSerializerSettings); Debug.WriteLine(json2); if (!JToken.DeepEquals(JToken.Parse(json), JToken.Parse(json2))) throw new InvalidOperationException("Round Trip Failed"); }
I get the following exception:
Newtonsoft.Json.JsonSerializationException: Additional text found in JSON string after finishing deserializing object. at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 196 at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\JsonSerializer.cs:line 823 at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\JsonSerializer.cs:line 802 at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\JsonConvert.cs:line 863 at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\JsonConvert.cs:line 820 at Question34654184.TestClass.TestRoundTrip[T](T item, JsonSerializerSettings jsonSerializerSettings) at Question34654184.TestClass.TestRoundTrip[T](T item) at Question34654184.TestClass.TestSimple()
An exception does not occur in Json 7.0. You must report a problem .
In the meantime, you can use the following converter to solve the problem:
public class ByteArrayConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(byte[]); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var token = JToken.Load(reader); if (token == null) return null; switch (token.Type) { case JTokenType.Null: return null; case JTokenType.String: return Convert.FromBase64String((string)token); case JTokenType.Object: { var value = (string)token["$value"]; return value == null ? null : Convert.FromBase64String(value); } default: throw new JsonSerializationException("Unknown byte array format"); } } public override bool CanWrite { get { return false; } }
With settings
var jsonSerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple, Converters = new [] { new ByteArrayConverter() }, };