Wson中的JsonConvert.DeserializeObject和“d”包装器

时间:2009-10-26 15:32:16

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

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

如果我使用 JsonConvert.DeserializeObject(响应)进行解析,其中响应为

"{\"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?

7 个答案:

答案 0 :(得分:11)

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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

把你的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中的字符串粘贴到同一个在线类生成器中,并且您将拥有创建接收对象类型所需的代码!

答案 3 :(得分:0)

现在我摆脱了使用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'.

诀窍在哪里?

答案 4 :(得分:0)

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

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

希望这有帮助!

答案 5 :(得分:0)

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

答案 6 :(得分:0)

也许这有帮助。

服务:

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>