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


  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库进行解码。

更新

这在Json中是固定的。. NET 7.0 Release 1.

原始回答

这是一个Json。网络问题。问题是,您的字符串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解码短路。这是一个丑陋的bug,而且你获得这个字符串的运气很差。

阻止Json。. NET不适当的GUID识别,您可以为字节数组创建自己的全局JsonConverter。当你这样做时,Json。. NET将传递给你没有"helpful" 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() }
        };

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

问题是JObject已经将AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA解析为string (j["responseArray"].Type == JTokenType.String),因此j["responseArray"].ToObject<byte[]>没有做de-base64。

您必须将其直接解析为byte[],如:

public class MyObject
{
    public byte[] responseArray { get; set; }
}
MyObject cl = JsonConvert.DeserializeObject<MyObject>("{'responseArray':'AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA'}");

显然你可以"手动"完成Convert.FromBase64String:

JObject j = JObject.Parse("{'responseArray':'AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA'}");
byte[] r = Convert.FromBase64String((string)j["responseArray"]);

相关内容

  • 没有找到相关文章

最新更新