【问题标题】:JsonConvert.DeserializeObject and "d" wrapper in WCFWCF 中的 JsonConvert.DeserializeObject 和“d”包装器
【发布时间】:2009-10-26 15:32:15
【问题描述】:

默认情况下,WCF 服务将 JSON 响应包装在“d”包装器中,在那里我发现解析它的问题。

如果我用 JsonConvert.DeserializeObject(response) 解析其中响应是

"{\"d\":\"{\"a0b70d2f-7fe4-4aa2-b600-066201eab82d\":\"Thelma\",\"d56d4d4f-6029-40df-a23b-de27617a1e43\":\"Louise\"}\"}"

我遇到了错误:

After parsing a value an unexpected character was encoutered: a. Line 1, position 9.

如果我将响应更改为

"{\"a0b70d2f-7fe4-4aa2-b600-066201eab82d\":\"Thelma\",\"d56d4d4f-6029-40df-a23b-de27617a1e43\":\"Louise\"}"

我搞定了。

那么如何解析来自 WCF 服务的这个“d”包装的 JSON 响应呢?有没有更好的解析 JSON 的方法?

【问题讨论】:

    标签: c# .net wcf json json.net


    【解决方案1】:

    我假设您在行为配置中使用 <enableWebScript/>,将其替换为 <webHttp defaultOutgoingResponseFormat="Json"/>,您将获得干净整洁的 json,没有“d”和“__type”

    【讨论】:

    • 如果您删除<enableWebScript/>,您将无法通过 jquery 中的 ajax 请求访问该服务
    【解决方案2】:

    看起来您正在 webHttpBinding 上使用 enableWebScript 行为。您可能应该改用 webHttp 行为 - 这为您提供“干净”的 JSON 而不是 ASP.NET AJAX 客户端 JSON。

    【讨论】:

    • 我尝试更改此设置,但随后出现错误:合同“组织”的操作“保存”指定要序列化的多个请求正文参数,无需任何包装器元素。最多一个 body 参数可以在没有包装元素的情况下被序列化。删除额外的正文参数或将 WebGetAttribute/WebInvokeAttribute 上的 BodyStyle 属性设置为 Wrapped。我的保存方法如下所示: [OperationContract] bool Save(string orgGuid, string orgName, string orgCode, string orgAddress, int orgStatus) 否则这个“d”包装是可以的,但为什么它会在解析时产生错误?
    【解决方案3】:

    获取您的 json 并将其粘贴到在线课程生成器中,例如 http://httputility.net/json-to-csharp-vb-typescript-class.aspx。它将为您提供反序列化此 json 对象的代码,如下所示(VB 示例):

    Public Class MyClass
         Public Property D As String
    End Class
    

    将其粘贴到您的项目中并将 json 反序列化到该对象中。 D 属性现在是一个字符串,其中包含您需要再次反序列化到最终接收对象中的未包装 json。如果您不确定需要处理的类,请将 D 中的字符串粘贴到同一个在线类生成器中,您将拥有创建接收对象的类型所需的代码!

    【讨论】:

      【解决方案4】:

      现在我用 Regex.Replace 摆脱了“d”包装器,并用适当的结构修复 JSON 响应

      {\"Guid\":\"a0b70d2f-7fe4-4aa2-b600-066201eab82d\",\"Name\":\"Thelma\"}
      {\"Guid\":\"d56d4d4f-6029-40df-a23b-de27617a1e43\",\"Name\":\"Lousie\"}\"}
      

      我还创建了一个带有 Guid 和 Name 的类,在其中定义为字符串。

      然后尝试用

      反序列化它
      List<myStruct> o = JsonConvert.DeserializeObject<List<myStruct>>(response);
      

      但我得到一个错误

      Expected a JsonObjectContract or JsonDictionaryContract for type 'System.Collections.Generic.List`1[mynamespace.myStruct]', got 'Newtonsoft.Json.Serialization.JsonArrayContract'.
      

      诀窍在哪里?

      【讨论】:

      • 我正在检查james.newtonking.com/projects/json-net.aspx 上的示例。好的,如果您在 JSON 字符串中只有一条记录,这一切都很好,但如果您有更多记录...
      • 你也在反序列化什么?我们可以看看 mystruct 吗?
      【解决方案5】:

      如果您切换到 WebHttpBehavior 并且仍然收到有关未包装的正文元素的错误消息,请手动将您正在处理的方法的正文样式设置为已包装。这样做:

      [OperationContract(BodyStyle = WebMessageBodyStyle.Wrapped, ...)] 字符串 DoSomething(...)

      希望这会有所帮助!

      【讨论】:

        【解决方案6】:

        你可以有一个反序列化包装类,它有一个名为“d”的属性。一旦你成功反序列化到它,然后从 d 属性中获取值。

        【讨论】:

          【解决方案7】:

          也许这会有所帮助。

          服务:

          namespace Application.Service
          {
                  [ServiceBehavior(UseSynchronizationContext = false,
                  ConcurrencyMode = ConcurrencyMode.Multiple,
                  InstanceContextMode = InstanceContextMode.PerCall),
                  AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
                  public class VendorService : IVendorService
                  {
                    public List<Vendor> RetrieveMultiple(int start, int limit, string sort, string dir)
                    {
                       //I don't do any manual serialization
                       return new Vendor();
                    }
                  }
          }
          

          合同:

              [ServiceContract(Namespace = "Application.Service.Contracts")]            
              public interface IVendorService
              {
                 [OperationContract]
                 [WebInvoke(ResponseFormat=WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
                  List<Vendor> RetrieveMultiple(int start, int limit, string sort, string dir);
               }
          

          我的 Svc 文件只有这一行:

          <%@ ServiceHost Service="Application.Service.VendorService" %>
          

          Web.config

          <system.serviceModel>
              <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
              <behaviors>
                <endpointBehaviors>
                  <behavior name="jsonBehavior">
                    <enableWebScript />
                    <webHttp />
                  </behavior>
                </endpointBehaviors>
                <serviceBehaviors>
                  <behavior name="DefaultServiceBehavior">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                  </behavior>
                  <behavior name="">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                  </behavior>
                </serviceBehaviors>
              </behaviors>
          
            <service behaviorConfiguration="DefaultServiceBehavior" name="Application.Service.VendorService">
              <endpoint behaviorConfiguration="jsonBehavior" address="" binding="webHttpBinding" contract="Application.Service.Contracts.IVendor" />
            </service>
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-11-24
            • 2018-01-16
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多