Question

By default WCF service wrap JSON response in "d" wrapper and there I found a problem with parsing it.

If I parse with JsonConvert.DeserializeObject(response) where response is

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

I gor an Error:

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

If I change response into

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

I got it working.

So how to parse this "d" wrapped JSON responses from WCF services? Is there any better way to parse JSON?

Was it helpful?

Solution 4

Now I got rid of "d" wrapper with Regex.Replace and fix JSON response with proper structure

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

I also make a class with Guid and Name, defined as string in it.

Then try to deserialize it with

List<myStruct> o = JsonConvert.DeserializeObject<List<myStruct>>(response);

But i get an error

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

Where is the trick?

OTHER TIPS

I'm assuming you are using <enableWebScript/> in your behavior config, replace that with <webHttp defaultOutgoingResponseFormat="Json"/> and you will get nice and clean json, no "d" and no "__type"

Looks like you're using the enableWebScript behavior on your webHttpBinding. You should probably be using the webHttp behavior instead- this gives you "clean" JSON instead of the ASP.NET AJAX client JSON.

Take your json and paste it into an online class generator, like http://httputility.net/json-to-csharp-vb-typescript-class.aspx. It will provide you the code to deserialize this json object into, like this (VB example):

Public Class MyClass
     Public Property D As String
End Class

Paste this into your project and deserialize the json into this object. The D property now is a string that contains the unwrapped json you'll need to deserialize a second time into your final receiving object. If you are unsure of the class you'll need to handle it, paste the string in D into the same online class generator and you'll have the code necessary to create the type to receive the object!

If you are switching to WebHttpBehavior and you still get an error message about the body elements not being wrapped, manually set the body style of the methods you're dealing with to Wrapped. Do it like so:

[OperationContract(BodyStyle = WebMessageBodyStyle.Wrapped, ...)] string DoSomething(...)

Hope this helps!

You could have a deserialization wrapper class that has one property called "d". Once you've successfully deserialized to it then get the value from the d property.

Maybe this helps.

The service:

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();
          }
        }
}

The contract:

    [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);
     }

My Svc file has just this line:

<%@ 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>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top