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"]);