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 函数解决的其他一些问题。

谢谢。