views:

9170

answers:

6

I'm attempting to use the following code to serialize an anonymous type to JSON:

var serializer = new DataContractJsonSerializer(thing.GetType());
var ms = new MemoryStream();
serializer.WriteObject(ms, thing);
var json = Encoding.Default.GetString(ms.ToArray()); 

However, I get the following exception when this is executed:

Type '<>f__AnonymousType1`3[System.Int32,System.Int32,System.Object[]]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. See the Microsoft .NET Framework documentation for other supported types.

I can't apply attributes to an anonymous type (as far as I know). Is there another way to do this serialization or am I missing something?

+27  A: 

Try the JavaScriptSerializer instead of the DataContractJsonSerializer

JavaScriptSerializer serializer = new JavaScriptSerializer();
var output = serializer.Serialize(your_anon_object);
Nick Berardi
One hitch though. The JavaScriptSerializer has been deprecated.
Biswanath
Trackback, it seems it was de-deprecated in SP1.
Biswanath
for something so obsolute, it appears to be getting used in many new Microsoft frameworks, including MVC. http://aspnet.codeplex.com/SourceControl/changeset/view/21528#266491
Nick Berardi
Works great for debugging in a test project with mock data.
jpierson
How do I include this i a non-asp.net project (console application)?
Alxandr
@Alxandr: You would need to reference `System.Web.Extensions.dll` and add a `using System.Web.Script.Serialization;` statement.
randomguy
@randomgui problem was project output type was set to client-profile.
Alxandr
+5  A: 

Check this article:

Tip/Trick: Building a ToJSON() Extension Method using .NET 3.5

CMS
+5  A: 

I would argue that you shouldn't be serializing an anonymous type. I know the temptation here; you want to quickly generate some throw-away types that are just going to be used in a loosely type environment aka Javascript in the browser. Still, I would create an actual type and decorate it as Serializable. Then you can strongly type your web methods. While this doesn't matter one iota for Javascript, it does add some self-documentation to the method. Any reasonably experienced programmer will be able to look at the function signature and say, "Oh, this is type Foo! I know how that should look in JSON."

Having said that, you might try JSON.Net to do the serialization. I have no idea if it will work

Jason Jackson
JSON.Net works just fine. I would argue that you shouldn't :), I think it's pretty legitimate in many cases.
aprilchild
After seeing the "throw away" types being used in MVC I can see some compelling uses. I think it is a very handy tool to have in your .Net tool box.
Matthew Whited
This is a point I have also softened on, especially in the case of consumption-only types. But if the object is making a return trip to the server, or is used in more than one location, I still believe that creating a type will result in fewer problems.
Jason Jackson
+2  A: 

Use the Newtonsoft JSON library.

aprilchild
A: 

Assuming you are using this for a web service, you can just apply the following attribute to the class:

[System.Web.Script.Services.ScriptService]

Then the following attribute to each method that should return Json:

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

And set the return type for the methods to be "object"

Paul
For a standard ASP web service [ScriptMethod(ResponseFormat = ResponseFormat.Json)] is not needed on the method, [WebMethod] will do.Also you should not set the return type to object, it can and should be strongly typed with a non-complex (i.e. can be serialized) type.
row1
A: 

You can try my ServiceStack JsonSerializer it's the fastest .NET JSON serializer at the moment. It supports serializing DataContract's, Any POCO Type, Interfaces, Late-bound objects including anonymous types, etc.

Basic Example

var customer = new Customer { Name="Joe Bloggs", Age=31 };
var json = JsonSerializer.SerializeToString(customer);
var fromJson = JsonSerializer.DeserializeFromString<Customer>(json); 

Note: Only use Microsofts JavaScriptSerializer if performance is not important to you as I've had to leave it out of my benchmarks since its up to 40x-100x slower than the other JSON serializers.

mythz