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 库的原因解码。
最佳答案
更新
这是 fixed在 Json.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/