How to not serialize the __type property on JSON objects

Solution 1:

I found that if I make the default constructor of my class that my webmethod returns anything other than public it will not serialize the __type:ClassName portion.

You may want to declare your default constructor protected internal ClassName() { }

Solution 2:

John's solution didn't work for me as the type I'm returning is in a seperate DLL. I have full control over that DLL but I can't construct my return type if the constructor is internal.

I wondered if the return type being a public type in a library might even be the cause - I've been doing a lot of Ajax and not seen this one before.

Quick tests:

  • Temporarily moved the return type declaration into App_Code. Still get __type serialised.

  • Ditto and applied the protected internal constructor per JM. This worked (so he gets a vote).

Strangely I don't get __type with a generic return type:

[WebMethod]
public static WebMethodReturn<IEnumerable<FleetObserverLiteAddOns.VehicleAddOnAccountStatus>> GetAccountCredits()

The solution for me, however, was to leave my return type in the DLL but change the WebMethod return type to object, i.e.

[WebMethod]
public static object ApplyCredits(int addonid, int[] vehicleIds) 

instead of

[WebMethod]
public static WebMethodReturn ApplyCredits(int addonid, int[] vehicleIds)

Solution 3:

I've been trying some of these suggestions with a .NET 4 WCF service, and they don't seem to work - the JSON response still includes __type.

The easiest way I've discovered to remove the type-hinting is to change the endpoint behaviour from enableWebScript to webHttp.

    <behavior name="MapData.MapDataServiceAspNetAjaxBehavior">
      <webHttp />
    </behavior>

The default enableWebScript behaviour is required if you're using an ASP.NET AJAX client, but if you're manipulating the JSON with JavaScript or jQuery then the webHttp behaviour is probably a better choice.

Solution 4:

If you're using ServiceStack.Text JSON Serializer you just need to:

JsConfig.ExcludeTypeInfo = true;

This functionality was automatically added back in v2.28, but the code above keeps that out of the serialization. You can also change this behavior by Type with:

JsConfig<Type>.ExcludeTypeInfo = true;

Solution 5:

I think I have narrowed down the root cause of the mysterious appearing "__type" !

Here is an example where you can recreate the issue.

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class Test : System.Web.Services.WebService
{
    public class Cat
    {
        public String HairType { get; set; }
        public int MeowVolume { get; set; }
        public String Name { get; set; }
    }

    [WebMethod]
    public String MyMethodA(Cat cat)
    {
        return "return value does not matter";
    }

    [WebMethod]
    public Cat MyMethodB(String someParam)
    {
        return new Cat() { HairType = "Short", MeowVolume = 13, Name = "Felix the Cat" };
    }
}

Here is the key part!

Simply because MyMethodA() exists in this same .asmx file and takes the class Cat as a parameter.... the __type will be added to the JSON returned from calling the other method: MyMethodB().

Even though they are different methods!!

My theory is as follows:

  1. When writing web services like this, Microsoft's code automatically hooks up the JSON serializing/deserializing behavior for you since you used the correct attributes, like [WebMethod] and [ScriptService].
  2. When this auto-magic Microsoft code executes, it finds a method that takes in Cat class as a parameter.
  3. It figures... oh... ok.... well since I will be receiving a Cat object from JSON.... therefore... if I ever return a Cat object as JSON from any method in the current web service class... I will give it a __type property so it will be easy to identify later when deserializing back to C#.
  4. Nyah-hahahaha...

Important Take-Away Note

You can avoid having the __type property appear in your generated JSON by avoiding taking in the class in question (Cat in my case) as a parameter to any of your WebMethods in your web service. So, in the above code, simply try modifying MyMethodA() to remove the Cat parameter. This causes the __type property to not be generated.