WCF Json 使用 newtonsoft json 导致反序列化错误
WCF Json result deserialization error with newtonsoft json
我正在尝试创建一个 WCF Json 在 WPF Phone 8.1 应用程序(不是 silverlight)中休息和使用相同的内容。
我的 WCF 是:
<OperationContract()>
<WebGet(UriTemplate:="getdata", ResponseFormat:=WebMessageFormat.Json)>
Function DoWork() As Dictionary(Of Integer, String)
WCF 代码:
Public Class BasicService
Implements IBasicService
Public Function DoWork() As Dictionary(Of Integer, String) Implements IBasicService.DoWork
Dim k As New Dictionary(Of Integer, String)
k.Add(1, "One")
k.Add(2, "Two")
Return k
End Function
End Class
Phone消费码:
Dim httpCli As New System.Net.Http.HttpClient()
Dim httpres As Task(Of HttpResponseMessage) = httpCli.GetAsync("http://localhost:4149/BasicService.svc/getdata")
Dim tk As Task(Of String)
tk = httpres.Result.Content.ReadAsStringAsync
Try
Dim resultstring As String = tk.Result.Substring(tk.Result.IndexOf("{"), tk.Result.LastIndexOf("}") + 1 - tk.Result.IndexOf("{"))
Dim DoWorkResult As Dictionary(Of Integer, String) = Newtonsoft.Json.JsonConvert.DeserializeObject(resultstring)
Catch ex As Exception
End Try
Try
Dim DoWorkResult As Dictionary(Of Integer, String) = Newtonsoft.Json.JsonConvert.DeserializeObject(tk.Result)
Catch ex As Exception
End Try
WCF 的 Fiddler 数据是:
原始:
HTTP/1.1 200 OK Cache-Control: private Content-Type: application/json;
charset=utf-8 Server: Microsoft-IIS/8.0 X-AspNet-Version: 4.0.30319
X-SourceFiles:
=?UTF-8?B?RTpcUmFnaGF2YVxpbXBcUHJvamVjdHNcTUNvbGxlY3RvclxNQ1dDRlxCYXNpY1NlcnZpY2Uuc3ZjXGdldGRhdGE=?=
X-Powered-By: ASP.NET Date: Mon, 15 Jun 2015 22:50:53 GMT
Content-Length: 49
[{"Key":1,"Value":"One"},{"Key":2,"Value":"Two"}]
网络视图:
[{"Key":1,"Value":"One"},{"Key":2,"Value":"Two"}]
在代码中反序列化时:
Error at first Try Catch with result text from '{' to '}' : Additional
text encountered after finished reading JSON content: ,. Path '', line
1, position 23.
第二个 Try Catch 未修改时出错 json 字符串:
Unable to cast object of type 'Newtonsoft.Json.Linq.JArray' to type
'System.Collections.Generic.Dictionary`2[System.Int32,System.String]'.
能否请您指正我哪里做错了或者我做错了什么。
您正在使用 Json.NET,但您的 json 字符串表示 DataContractJsonSerializer
as opposed to the simpler and more conventional Json.NET format 使用的格式的字典。
解决此问题的一种方法是切换到 DataContractJsonSerializer
,如下所示:VB.net JSON Deserialize。
如果您更喜欢坚持使用 Json.NET,则需要创建一个自定义 JsonConverter
,例如:
Public Class KeyValueDictionaryConverter(Of TKey, TValue)
Inherits JsonConverter
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return GetType(IDictionary(Of TKey, TValue)).IsAssignableFrom(objectType)
End Function
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
Dim array = serializer.Deserialize(Of KeyValuePair(Of TKey, TValue)())(reader)
If array Is Nothing Then
Return existingValue
End If
Dim dict = (If(TryCast(existingValue, IDictionary(Of TKey, TValue)), DirectCast(serializer.ContractResolver.ResolveContract(objectType).DefaultCreator()(), IDictionary(Of TKey, TValue))))
For Each pair As KeyValuePair(Of TKey, TValue) In array
dict.Add(pair.Key, pair.Value)
Next
Return dict
End Function
Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
serializer.Serialize(writer, DirectCast(value, IDictionary(Of TKey, TValue)).Select(Function(p) p))
End Sub
End Class
然后像这样使用它:
Dim json As String = "[{""Key"":1,""Value"":""One""},{""Key"":2,""Value"":""Two""}]"
Dim settings = New JsonSerializerSettings()
settings.Converters.Add(New KeyValueDictionaryConverter(Of Integer, String)())
Dim dict = JsonConvert.DeserializeObject(Of Dictionary(Of Integer, String))(json, settings)
加上断言所有内容都已读取的代码:
Dim json2 = JsonConvert.SerializeObject(dict, Newtonsoft.Json.Formatting.Indented, settings)
If Not JToken.DeepEquals(JToken.Parse(json), JToken.Parse(json2)) Then
Debug.Assert(JToken.DeepEquals(JToken.Parse(json), JToken.Parse(json2)))
Throw New ApplicationException("Tokens Not Equal")
End If
工作fiddle。
这不是最好的解决方案,但它解决了我对跨平台的基本需求,因为客户端和服务器代码是由我完成的,我使用响应格式 XMl 并且每个功能仅 returns string,但是函数 returns JSON 序列化了 string.
Dim k As New Dictionary(Of Integer, String)
k.Add(1, "One One ~ ! @ # $ % ^ & * ( ) _ + | , . / ; ' [ ] < > ? : "" { } - = \ / * - + ")
k.Add(2, "Two")
Return Newtonsoft.Json.JsonConvert.SerializeObject(k, Newtonsoft.Json.Formatting.None)
在客户端,我过滤从 { 到 } 的字符串并使用 json.net 反序列化。 :)
Dim resultstring As String = tk.Result.Substring(tk.Result.IndexOf("{"), tk.Result.LastIndexOf("}") + 1 - tk.Result.IndexOf("{"))
resultstring = Net.WebUtility.HtmlDecode(resultstring)
Dim DoWorkResult As Dictionary(Of Integer, String) = Newtonsoft.Json.JsonConvert.DeserializeObject(resultstring, GetType(Dictionary(Of Integer, String)))
我目前面临的错误是解决像“&”这样的特殊字符被发送为“&”以及我使用 HTMLDecode 函数解决的其他一些问题。
谢谢。
我正在尝试创建一个 WCF Json 在 WPF Phone 8.1 应用程序(不是 silverlight)中休息和使用相同的内容。
我的 WCF 是:
<OperationContract()>
<WebGet(UriTemplate:="getdata", ResponseFormat:=WebMessageFormat.Json)>
Function DoWork() As Dictionary(Of Integer, String)
WCF 代码:
Public Class BasicService
Implements IBasicService
Public Function DoWork() As Dictionary(Of Integer, String) Implements IBasicService.DoWork
Dim k As New Dictionary(Of Integer, String)
k.Add(1, "One")
k.Add(2, "Two")
Return k
End Function
End Class
Phone消费码:
Dim httpCli As New System.Net.Http.HttpClient()
Dim httpres As Task(Of HttpResponseMessage) = httpCli.GetAsync("http://localhost:4149/BasicService.svc/getdata")
Dim tk As Task(Of String)
tk = httpres.Result.Content.ReadAsStringAsync
Try
Dim resultstring As String = tk.Result.Substring(tk.Result.IndexOf("{"), tk.Result.LastIndexOf("}") + 1 - tk.Result.IndexOf("{"))
Dim DoWorkResult As Dictionary(Of Integer, String) = Newtonsoft.Json.JsonConvert.DeserializeObject(resultstring)
Catch ex As Exception
End Try
Try
Dim DoWorkResult As Dictionary(Of Integer, String) = Newtonsoft.Json.JsonConvert.DeserializeObject(tk.Result)
Catch ex As Exception
End Try
WCF 的 Fiddler 数据是: 原始:
HTTP/1.1 200 OK Cache-Control: private Content-Type: application/json; charset=utf-8 Server: Microsoft-IIS/8.0 X-AspNet-Version: 4.0.30319 X-SourceFiles: =?UTF-8?B?RTpcUmFnaGF2YVxpbXBcUHJvamVjdHNcTUNvbGxlY3RvclxNQ1dDRlxCYXNpY1NlcnZpY2Uuc3ZjXGdldGRhdGE=?= X-Powered-By: ASP.NET Date: Mon, 15 Jun 2015 22:50:53 GMT Content-Length: 49
[{"Key":1,"Value":"One"},{"Key":2,"Value":"Two"}]
网络视图:
[{"Key":1,"Value":"One"},{"Key":2,"Value":"Two"}]
在代码中反序列化时:
Error at first Try Catch with result text from '{' to '}' : Additional text encountered after finished reading JSON content: ,. Path '', line 1, position 23.
第二个 Try Catch 未修改时出错 json 字符串:
Unable to cast object of type 'Newtonsoft.Json.Linq.JArray' to type 'System.Collections.Generic.Dictionary`2[System.Int32,System.String]'.
能否请您指正我哪里做错了或者我做错了什么。
您正在使用 Json.NET,但您的 json 字符串表示 DataContractJsonSerializer
as opposed to the simpler and more conventional Json.NET format 使用的格式的字典。
解决此问题的一种方法是切换到 DataContractJsonSerializer
,如下所示:VB.net JSON Deserialize。
如果您更喜欢坚持使用 Json.NET,则需要创建一个自定义 JsonConverter
,例如:
Public Class KeyValueDictionaryConverter(Of TKey, TValue)
Inherits JsonConverter
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return GetType(IDictionary(Of TKey, TValue)).IsAssignableFrom(objectType)
End Function
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
Dim array = serializer.Deserialize(Of KeyValuePair(Of TKey, TValue)())(reader)
If array Is Nothing Then
Return existingValue
End If
Dim dict = (If(TryCast(existingValue, IDictionary(Of TKey, TValue)), DirectCast(serializer.ContractResolver.ResolveContract(objectType).DefaultCreator()(), IDictionary(Of TKey, TValue))))
For Each pair As KeyValuePair(Of TKey, TValue) In array
dict.Add(pair.Key, pair.Value)
Next
Return dict
End Function
Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
serializer.Serialize(writer, DirectCast(value, IDictionary(Of TKey, TValue)).Select(Function(p) p))
End Sub
End Class
然后像这样使用它:
Dim json As String = "[{""Key"":1,""Value"":""One""},{""Key"":2,""Value"":""Two""}]"
Dim settings = New JsonSerializerSettings()
settings.Converters.Add(New KeyValueDictionaryConverter(Of Integer, String)())
Dim dict = JsonConvert.DeserializeObject(Of Dictionary(Of Integer, String))(json, settings)
加上断言所有内容都已读取的代码:
Dim json2 = JsonConvert.SerializeObject(dict, Newtonsoft.Json.Formatting.Indented, settings)
If Not JToken.DeepEquals(JToken.Parse(json), JToken.Parse(json2)) Then
Debug.Assert(JToken.DeepEquals(JToken.Parse(json), JToken.Parse(json2)))
Throw New ApplicationException("Tokens Not Equal")
End If
工作fiddle。
这不是最好的解决方案,但它解决了我对跨平台的基本需求,因为客户端和服务器代码是由我完成的,我使用响应格式 XMl 并且每个功能仅 returns string,但是函数 returns JSON 序列化了 string.
Dim k As New Dictionary(Of Integer, String)
k.Add(1, "One One ~ ! @ # $ % ^ & * ( ) _ + | , . / ; ' [ ] < > ? : "" { } - = \ / * - + ")
k.Add(2, "Two")
Return Newtonsoft.Json.JsonConvert.SerializeObject(k, Newtonsoft.Json.Formatting.None)
在客户端,我过滤从 { 到 } 的字符串并使用 json.net 反序列化。 :)
Dim resultstring As String = tk.Result.Substring(tk.Result.IndexOf("{"), tk.Result.LastIndexOf("}") + 1 - tk.Result.IndexOf("{"))
resultstring = Net.WebUtility.HtmlDecode(resultstring)
Dim DoWorkResult As Dictionary(Of Integer, String) = Newtonsoft.Json.JsonConvert.DeserializeObject(resultstring, GetType(Dictionary(Of Integer, String)))
我目前面临的错误是解决像“&”这样的特殊字符被发送为“&”以及我使用 HTMLDecode 函数解决的其他一些问题。
谢谢。