.net - 反序列化 base64 编码的字节数组在 2 个 JSON.net 库版本中返回不同的结果

标签 .net json.net base64

  JObject j = JObject.Parse("{'responseArray':'AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA'}");

  byte[] r = j["responseArray"].ToObject<byte[]>(JsonSerializer.Create(new JsonSerializerSettings()));

预期输出(适用于 JSON.net v4.5.6.14930)
r =  {byte[24]}
        [0]: 0
        [1]: 0
        [2]: 0
        [3]: 0
        [4]: 0
        [5]: 0
        [6]: 0
        [7]: 0
        [8]: 0
        [9]: 0
        [10]: 0
        [11]: 0
        [12]: 0
        [13]: 0
        [14]: 0
        [15]: 0
        [16]: 0
        [17]: 0
        [18]: 0
        [19]: 0
        [20]: 1
        [21]: 0
        [22]: 0
        [23]: 0

在 JSON.net v6.0.8.18111 中反序列化上述代码给出错误结果

不正确的输出 (JSON.net v6.0.8.18111)
r= {byte[16]}
    [0]: 170
    [1]: 170
    [2]: 170
    [3]: 170
    [4]: 170
    [5]: 170
    [6]: 170
    [7]: 170
    [8]: 170
    [9]: 170
    [10]: 170
    [11]: 170
    [12]: 170
    [13]: 171
    [14]: 170
    [15]: 170

我在这里做错了吗?

笔记-
问题中的片段是一段复杂代码的一部分,其中数据作为 WebMethod 的 JSON 参数传入,responsearray 是发送到 webmethod 的复杂对象的一部分,这就是我们使用 JSON.net 库的原因解码。

最佳答案

更新

这是 fixedJson.NET 7.0 Release 1 .

原答案

这是一个 Json.NET 问题。问题是你的字符串 AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA恰好可以成功解析为 GUID,在 JsonReader.ReadAsBytesInternal() :

            if (s.Length == 0)
            {
                data = new byte[0];
            }
            else if (ConvertUtils.TryConvertGuid(s, out g))
            {
                data = g.ToByteArray();
            }
            else
            {
                data = Convert.FromBase64String(s);
            }

在此回溯中:
Newtonsoft.Json.JsonReader.ReadAsBytesInternal() Line 517   C#
Newtonsoft.Json.Linq.JTokenReader.ReadAsBytes() Line 74 + 0x9 bytes C#
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(Newtonsoft.Json.JsonReader reader = {Newtonsoft.Json.Linq.JTokenReader}, Newtonsoft.Json.Serialization.JsonContract contract = {Newtonsoft.Json.Serialization.JsonPrimitiveContract}, bool hasConverter = false) Line 1853 + 0x8 bytes   C#
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(Newtonsoft.Json.JsonReader reader = {Newtonsoft.Json.Linq.JTokenReader}, System.Type objectType = {Name = "Byte[]" FullName = "System.Byte[]"}, bool checkAdditionalContent = false) Line 144 + 0x2f bytes   C#
Newtonsoft.Json.JsonSerializer.DeserializeInternal(Newtonsoft.Json.JsonReader reader = {Newtonsoft.Json.Linq.JTokenReader}, System.Type objectType = {Name = "Byte[]" FullName = "System.Byte[]"}) Line 710 + 0x52 bytes    C#
Newtonsoft.Json.JsonSerializer.Deserialize(Newtonsoft.Json.JsonReader reader = {Newtonsoft.Json.Linq.JTokenReader}, System.Type objectType = {Name = "Byte[]" FullName = "System.Byte[]"}) Line 689 + 0x11 bytes    C#
Newtonsoft.Json.Linq.JToken.ToObject(System.Type objectType = {Name = "Byte[]" FullName = "System.Byte[]"}, Newtonsoft.Json.JsonSerializer jsonSerializer = {Newtonsoft.Json.JsonSerializer}) Line 1837 + 0x11 bytes    C#
Newtonsoft.Json.Linq.JToken.ToObject(System.Type objectType = {Name = "Byte[]" FullName = "System.Byte[]"}) Line 1811 + 0x3c bytes  C#
Newtonsoft.Json.Linq.JToken.ToObject<byte[]>() Line 1698 + 0x39 bytes   C#

如您所见,这会使 base 64 解码短路。丑陋的错误,而您获得该确切字符串的运气不佳。

要阻止 Json.NET 的不当 GUID 识别,您可以创建自己的全局 JsonConverter对于字节数组。当您这样做时,Json.NET 将向您传递没有“有用”GUID 模式匹配的原始字符串:
public class ByteConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(byte[]);
    }

    public override bool CanWrite { get { return false; } } // Use the default implementation for serialization, which is not broken.

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var value = (string)JToken.Load(reader);
        if (value == null)
            return null;
        if (value.Length == 0)
            return new byte[0];
        return Convert.FromBase64String(value);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后,全局设置它:
        JsonConvert.DefaultSettings = () => new JsonSerializerSettings
        {
            Converters = new List<JsonConverter> { new ByteConverter() }
        };

此解决方法可恢复字节数组的正确反序列化。

关于.net - 反序列化 base64 编码的字节数组在 2 个 JSON.net 库版本中返回不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30369274/

相关文章:

c# - 尝试将 JSON 转换为 [Key,Value] 字典

java - 如果解码,两个不同的 BASE 64 编码字符串是否会产生相同的字符串?

PHP自编码算法

c# - 当编码以 + 开头时,Base64 解码中断

c# - 适用于 Windows xp、7、8 的最佳 .net 框架版本,无需单独安装或更新

c# - 使用 Moq 模拟 'new()' 约束

c# - 将WAV文件转换为字节数组会降低音频速度

c# - 使用 JSON.NET 添加 bool 属性

c# - 从第三方数据源导入数据(开放架构设计)

c# - Newtonsoft.Json.JsonConvert.DeserializeObject<T> 可以返回 null 吗?如何?