相关文章推荐
魁梧的风衣  ·  获取语句 (VBA) | ...·  3 周前    · 
知识渊博的帽子  ·  日常搬运——networkx返回图的邻接矩阵 ...·  2 年前    · 
买醉的篮球  ·  Ubuntu ...·  2 年前    · 
奔跑的香烟  ·  Vue处理静态资源及public/stati ...·  2 年前    · 
机灵的绿茶  ·  使用MySQL,请用好 JSON 这张牌! ...·  2 年前    · 
霸气的领结  ·  Django-admin连接mysql页面显 ...·  2 年前    · 
Code  ›  无法使用Json.NET 8.0.1反序列化具有字节数组属性的对象开发者社区
string 对象数组 序列化 字节数组
https://cloud.tencent.com/developer/ask/sof/112805534
侠义非凡的板栗
1 年前
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
提问

问 无法使用Json.NET 8.0.1反序列化具有字节数组属性的对象

Stack Overflow用户
提问于 2016-01-07 11:37:16
EN

在升级代码库以使用Json.NET 8.0.1之后,有些反序列化会出现问题。使用Json.NET 7.0.1,一切都很好。显然,导致问题的是 byte[] 类型属性的反序列化。如果我删除了 byte[] 属性,它就能正常工作。我可以使用这个简单的控制台应用程序再现这种行为:

代码语言: javascript
复制
internal class Program
    private static void Main(string[] args)
        Dictionary<string, Account> accounts;
        var jsonSerializerSettings = new JsonSerializerSettings
            TypeNameHandling = TypeNameHandling.Objects,
            TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
        using (var streamReader = new StreamReader("accounts.json"))
            var json = streamReader.ReadToEnd();
            accounts = JsonConvert.DeserializeObject<Dictionary<string, Account>>(json, jsonSerializerSettings);
        foreach (var account in accounts)
            Debug.WriteLine(account.Value.Name);
internal class Account
    public string Id { get; set; }
    public string Name { get; set; }
    public byte[] EncryptedPassword { get; set; }
}

accounts.json 文件如下所示:

代码语言: javascript
复制
{
    "$type": "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[ConsoleApplication1.Account, ConsoleApplication1]], mscorlib",
    "lars.michael": {
        "$type": "ConsoleApplication1.Account, ConsoleApplication1",
        "EncryptedPassword": {
            "$type": "System.Byte[], mscorlib",
            "$value": "cGFzc3dvcmQ="
        "Name": "Lars Michael",
        "Id": "lars.michael"
    "john.doe": {
        "$type": "ConsoleApplication1.Account, ConsoleApplication1",
        "EncryptedPassword": {
            "$type": "System.Byte[], mscorlib",
            "$value": "cGFzc3dvcmQ="
        "Name": "John Doe",
        "Id": "john.doe"
}

这可能是Json.NET 8.0.1中的一个bug,还是我可以通过调整 JsonSerializerSettings 来解决这个问题?

如果有人试图复制该程序集,请确保将 accounts.json 文件中的程序集名称与控制台应用程序的程序集名称(在本例中为 ConsoleApplication1 )同步。

1 4.9K 0 票数 5
EN
c#
serialization
json.net

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-07 14:10:33

更新

变更中的 固定 设置了 70120 ,它将包含在Json.NET 8.0.2中。

原始答案

确认-这似乎是一个倒退。考虑以下简单的测试类:

代码语言: javascript
复制
internal class HasByteArray
    public byte[] EncryptedPassword { get; set; }
}

现在,如果我试着用 TypeNameHandling.Objects 往返全班

代码语言: javascript
复制
    private static void TestSimple()
        var test = new HasByteArray { EncryptedPassword = Convert.FromBase64String("cGFzc3dvcmQ=") };
            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");
    }

我得到以下例外:

代码语言: javascript
复制
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()

Json7.0中没有出现异常。你应该 报告问题 。

同时,您可以使用以下转换器来解决问题:

代码语言: javascript
复制
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; } } // Use the default implementation for serialization, which is not broken.
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        throw new NotImplementedException();
 
推荐文章
魁梧的风衣  ·  获取语句 (VBA) | Microsoft Learn
3 周前
知识渊博的帽子  ·  日常搬运——networkx返回图的邻接矩阵_networkx 显示图的邻接矩阵_7:45am的博客-CSDN博客
2 年前
买醉的篮球  ·  Ubuntu 18.04运行OpenCvSharp异常解决方案_ssdnif的博客-CSDN博客
2 年前
奔跑的香烟  ·  Vue处理静态资源及public/static/assets目录的区别-腾讯云开发者社区-腾讯云
2 年前
机灵的绿茶  ·  使用MySQL,请用好 JSON 这张牌! - 知乎
2 年前
霸气的领结  ·  Django-admin连接mysql页面显示数据 - 简书
2 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号