237

I am trying to return some JSON from a WCF service. This service simply returns some content from my database. I can get the data. However, I am concerned about the format of my JSON. Currently, the JSON that gets returned is formatted like this:

{"d":"[{\"Age\":35,\"FirstName\":\"Peyton\",\"LastName\":\"Manning\"},{\"Age\":31,\"FirstName\":\"Drew\",\"LastName\":\"Brees\"},{\"Age\":29,\"FirstName\":\"Tony\",\"LastName\":\"Romo\"}]"} 

In reality, I would like my JSON to be formatted as cleanly as possible. I believe (I may be incorrect), that the same collection of results, represented in clean JSON, should look like so:

[{ "Age": 35, "FirstName": "Peyton", "LastName": "Manning" }, { "Age": 31, "FirstName": "Drew", "LastName": "Brees" }, { "Age": 29, "FirstName": "Tony", "LastName": "Romo" }] 

I have no idea where the “d” is coming from. I also have no clue why the escape characters are being inserted. My entity looks like the following:

[DataContract] public class Person { [DataMember] public string FirstName { get; set; } [DataMember] public string LastName { get; set; } [DataMember] public int Age { get; set; } public Person(string firstName, string lastName, int age) { this.FirstName = firstName; this.LastName = lastName; this.Age = age; } } 

The service that is responsible for returning the content is defined as:

[ServiceContract(Namespace = "")] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class TestService { [OperationContract] [WebGet(ResponseFormat = WebMessageFormat.Json)] public string GetResults() { List<Person> results = new List<Person>(); results.Add(new Person("Peyton", "Manning", 35)); results.Add(new Person("Drew", "Brees", 31)); results.Add(new Person("Tony", "Romo", 29)); // Serialize the results as JSON DataContractJsonSerializer serializer = new DataContractJsonSerializer(results.GetType()); MemoryStream memoryStream = new MemoryStream(); serializer.WriteObject(memoryStream, results); // Return the results serialized as JSON string json = Encoding.Default.GetString(memoryStream.ToArray()); return json; } } 

How do I return “clean” JSON from a WCF service? Thank you!

4
  • SOAP should return XML. You can use a REST endpoint to return JSON. Take a look stackoverflow.com/questions/186631/… Commented Sep 15, 2014 at 21:21
  • 4
    By the way, if anyone else comes across this and wonders why the "d" property is there, it's there to patch a JSON vulnerability. Removing it makes you vulnerable again. Commented Feb 2, 2015 at 14:14
  • 4
    @Alex - that Vulnerability depends on redefining the Array object, which is no longer possible in modern browsers. See stackoverflow.com/questions/16289894/… Commented Feb 20, 2015 at 20:52
  • That's good. :) Half my answer is still true though -- it WAS there to patch that vulnerability. Commented Feb 22, 2015 at 10:53

6 Answers 6

216

Change the return type of your GetResults to be List<Person>.
Eliminate the code that you use to serialize the List to a json string - WCF does this for you automatically.

Using your definition for the Person class, this code works for me:

public List<Person> GetPlayers() { List<Person> players = new List<Person>(); players.Add(new Person { FirstName="Peyton", LastName="Manning", Age=35 } ); players.Add(new Person { FirstName="Drew", LastName="Brees", Age=31 } ); players.Add(new Person { FirstName="Brett", LastName="Favre", Age=58 } ); return players; } 

results:

[{"Age":35,"FirstName":"Peyton","LastName":"Manning"}, {"Age":31,"FirstName":"Drew","LastName":"Brees"}, {"Age":58,"FirstName":"Brett","LastName":"Favre"}] 

(All on one line)

I also used this attribute on the method:

[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "players")] 

WebInvoke with Method= "GET" is the same as WebGet, but since some of my methods are POST, I use all WebInvoke for consistency.

The UriTemplate sets the URL at which the method is available. So I can do a GET on http://myserver/myvdir/JsonService.svc/players and it just works.

Also check out IIRF or another URL rewriter to get rid of the .svc in the URI.

Sign up to request clarification or add additional context in comments.

8 Comments

Cheeso - I tried this approach before I posted this question. When I use this approach, I get an error that says "Endpoints using 'UriTemplate' cannot be used with 'System.ServiceModel.Description.WebScriptEnablingBehavior'." What am I doing wrong? Thank you!
use <webHttp/> instead of <webScriptEnablingBehavior/> in your .config file.
OK, I replaced <enableWebScript /> with <webHttp/> and that worked.
MGowen - FYI, best bet when asking a new question is to ...open a new question, rather than posting the question as a comment to an old answer.
Favre sees what you did there.
|
94

If you want nice json without hardcoding attributes into your service classes,

use <webHttp defaultOutgoingResponseFormat="Json"/> in your behavior config

Comments

28

This is accomplished in web.config for your webservice. Set the bindingBehavior to <webHttp> and you will see the clean JSON. The extra "[d]" is set by the default behavior which you need to overwrite.

See in addition this blogpost: http://blog.clauskonrad.net/2010/11/how-to-expose-json-endpoint-from-wcf.html

Comments

8

I faced the same problem, and resolved it by changing the BodyStyle attribut value to "WebMessageBodyStyle.Bare" :

[OperationContract] [WebGet(BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "GetProjectWithGeocodings/{projectId}")] GeoCod_Project GetProjectWithGeocodings(string projectId); 

The returned object will no longer be wrapped.

Comments

2

When you are using GET Method the contract must be this.

[WebGet(UriTemplate = "/", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)] List<User> Get(); 

with this we have a json without the boot parameter

Aldo Flores @alduar http://alduar.blogspot.com

Comments

1

In your IServece.cs add the following tag : BodyStyle = WebMessageBodyStyle.Bare

 [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "Getperson/{id}")] List<personClass> Getperson(string id); 

1 Comment

can you also explain why BodyStyle can affect the result ?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.