WCF - How to serialize and deserialize in JSON?

25,659

Solution 1

The full objects you are looking for should be structured as:

[DataContract(Name="response")]
public class Response
{
    [DataMember(Name = "locations")]
    public IEnumerable<Location> Locations { get; set; }

    [DataMember(Name = "error")]
    public string Error { get; set; }
}

[DataContract(Name = "location")]
public class Location
{
    [DataMember(Name = "id")]
    public string Id { get; set; }

    [DataMember(Name = "name")]
    public string Name { get; set; }

    [DataMember(Name = "statusid")]
    public string StatusId { get; set; }
}

You need to setup the object hierarchy, as indicated by the { and }, as well as the IEnumerable / array properties, as indicated by the [ and ] from your desired JSON output.

The site can be confusing, as there are no simple examples, but please review Introducing JSON for a basic understanding of the syntax. Another good site I came along, with just some simple examples, was JSON and XML Serialization in ASP.NET Web API.

Thanks to some guidance by vittore, I noticed that to build the exact match to your JSON output, you will need objects like:

[DataContract]
public class ResponseParent
{
    [DataMember(Name = "response")]
    public Response ResponseInstance { get; set; }
}

[DataContract]
public class Response
{
    [DataMember(Name = "locations")]
    public LocationCollectionIntermediate Locations { get; set; }

    [DataMember(Name = "error")]
    public string Error { get; set; }
}

[DataContract]
public class LocationCollectionIntermediate
{
    [DataMember(Name = "location")]
    public IEnumerable<Location> Locations { get; set; }
}

[DataContract]
public class Location
{
    [DataMember(Name = "id")]
    public string Id { get; set; }

    [DataMember(Name = "name")]
    public string Name { get; set; }

    [DataMember(Name = "statusid")]
    public string StatusId { get; set; }
}

I've added these into a second code block here, because such a structure seems needlessly complicated. However, if you are in a position where you can change the expected output of your JSON, I'd go with the first block, with the additional change of making the two Id columns into int types.

These types were created to support a service similar to as setup at WCF Service to return JSON, and tested using the following code:

string json;
using (var ms = new MemoryStream())
{
    var ser = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(ResponseParent));
    ser.WriteObject(ms, r);
    json = System.Text.Encoding.UTF8.GetString(ms.GetBuffer(), 0, Convert.ToInt32(ms.Length)); 
}

Details on DataContractJsonSerializer

Note also that if you have the option to setup a RESTful web service, then you can follow the guidelines of How to create a JSON WCF RESTful Service in 60 seconds.

Solution 2

Visit http://json.codeplex.com/. Use

JsonConvert.SerializeObject()

to turn your object into a JSON string. Use

JsonConvert.PopulateObject

to turn JSON string into an object.

Solution 3

Once you have the exact, attributed structure, you can also use the JavaScriptSerializer class from System.Web.Script.Serialization (since .NET 3.5)

Something like this will work:

string jsonString;

JavaScriptSerializer serializer = new JavaScriptSerializer();
Response responseObject = serializer.Deserialize<Response>(jsonString);

Even simpler than using DataContractSerializer, though I'm not entirely sure about its caveats. I have used it several times without any problems.

You can also add custom JavaScriptConverters, which makes it possible to implement a nicer way of dynamic JSON parsing with relative ease.

Dynamic parsing is also very simple this way:

string jsonString;

JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic responseObject = serializer.Deserialize<object>(jsonString);

responseObject["locations"] = ...
Share:
25,659
Pavan Welihinda
Author by

Pavan Welihinda

Updated on August 05, 2022

Comments

  • Pavan Welihinda
    Pavan Welihinda almost 2 years

    I have written few classes (Data contracts and Service contracts) in WCF and i'm trying to serialize and deserialize in JSON. If i need the following JSON structure, how would i create the DataContract(s):

    {
      "response": {
        "locations": {
          "location": [
            {
              "id": "12",
              "name": "Hello",
              "statusid": "78"
            },
            {
              "id": "5",
              "name": "Ann",
              "statusid": "8"
            }
          ]
        },
        "error": "404 error"
      }
    }
    

    The structure above is pretty straight forward and under locations there can be several location details as mentioned above. So i need to get an array/list to "locations" data members as mentioned below. At the moment i have the following DataContract only:

    [DataContract]
        public class Response
        {
            [DataMember]
            public string locations { get; set; }
    
            [DataMember]
            public string error{ get; set; }
        }
    

    Please let me know how i can resolve this?

  • vittore
    vittore about 11 years
    I would rather name classes and properties appropriately according to c# codding standards (i e Location not location) and use hints in DataMember etc attributes ie [DataMember(Name="location")] public class Location
  • vittore
    vittore about 11 years
    Another thing I've just noticed that either topic starter has error in example json payload, or you will need to introduce another class as he has object locations with property location which is array of something ( apparently of what you called location object in your c# snippet)
  • Pavan Welihinda
    Pavan Welihinda about 11 years
    Thank you guys for the help. Mike, based on what serialization method have you implemented the above structures? The .Net serialization or JSON.NET? Because i was wondering if it can be done using native serialization.
  • Pavan Welihinda
    Pavan Welihinda about 11 years
    @Mike i have used the second block you have mentioned except for "ResponseParent" Data contract. I get the output similar to the following: { "response": { "locations": [ { "id": "3", "name": "something", "statusid": "3" }, { "id": "5", "name": "something", "statusid": "8" } ], "errorcode": "ok" } } What changes should i make to add a "location" tag for each of "id,name,statusid" pairs? Like the following: "locations": { "location": [ { .... }, "location": [ { ...
  • Mike Guthrie
    Mike Guthrie about 11 years
    @PavanWelihinda I think you mean "locations" : [{"location" : {...}}, "location" : {...}}]. Notice how you are changing the hierarchical arrangement of the [ ]. What would make this change in your object model? In this case, Response would have the array of LocationCollectionIntermediate and LocationCollectionIntermediate would have just a single Location, while the DataMember names would remain the same.
  • garaber
    garaber about 10 years
    I hope that you guys are still watching this thread. I would love to see these data contracts fleshed out. I'm working on a Database transaction manager using JSON. Just started throwing mud at that chicken wire fence and more is sticking, forgive the metaphor. I'm started to catch on to some of the aspects of JSON serialization but would love to see the enumeration of location fleshed out. Thanks Guys.