Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

DataTable JSON Serialization in JSON.NET and JavaScriptSerializer


:P
On this page:

I've been thinking about replacing the JSON serializer in my internal codebase for some time and finally put a little effort into allowing JSON.NET from James Newton King to be plugged into my Ajax framework as a replaceable engine. My own parser has served me well, but JSON.NET is a much cleaner design and more flexible especially when dealing with extensibility. There are also a few nice features like the ability to pretty-format the generated JSON for debugging purposes which is immensely helpful when sending data to the client during development.

Although I'm keeping my original parser class (including original basic functionality) JSON.NET can now be optionally plugged in. So why not just replace the parser altogether? As it turns out I've been experimenting with different JSON serializer/deserializers and being able to keep a 'high level' wrapper object into which each of these parsers can be plugged into has been a great time saver as the interface that various application components use doesn't change one bit which is nice indeed.

Anyway, here's the basic code to provide JSON encoding and deserialization in a simple wrapper functions:

public string Serialize(object value)
{
    Type type = value.GetType();

    Newtonsoft.Json.JsonSerializer json = new Newtonsoft.Json.JsonSerializer();

    json.NullValueHandling = NullValueHandling.Ignore;
    
    json.ObjectCreationHandling = Newtonsoft.Json.ObjectCreationHandling.Replace;
    json.MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore;
    json.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

    if (type == typeof(DataRow))            
        json.Converters.Add(new DataRowConverter());
    else if(type == typeof(DataTable))
        json.Converters.Add(new DataTableConverter());
    else if (type == typeof(DataSet))
        json.Converters.Add(new DataSetConverter());
    
    StringWriter sw = new StringWriter();
    Newtonsoft.Json.JsonTextWriter writer = new JsonTextWriter(sw);
    if (this.FormatJsonOutput)
        writer.Formatting = Formatting.Indented;
    else
        writer.Formatting = Formatting.None;

    writer.QuoteChar = '"';
    json.Serialize(writer, value);
    
    string output = sw.ToString();
    writer.Close(); 
    sw.Close();
    
    return output;
}

public object Deserialize(string jsonText, Type valueType)
{
    Newtonsoft.Json.JsonSerializer json = new Newtonsoft.Json.JsonSerializer();
    
    json.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
    json.ObjectCreationHandling = Newtonsoft.Json.ObjectCreationHandling.Replace;
    json.MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore;
    json.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

    StringReader sr = new StringReader(jsonText);
    Newtonsoft.Json.JsonTextReader reader = new JsonTextReader(sr);            
    object result = json.Deserialize(reader, valueType);
    reader.Close();

    return result;
}

One of the nice things about the JSON.NET parser is that there are a tons of configuration options that allow you to customize how JSON parsing occurs. You can see some of the options above for things like null value handling and managing how deep recursive loops should be handled for example.

JSON.NET also has a simplified JavaScriptConvert class that has much simpler serialization and deserialization methods, but this wrapper doesn't have access to the configuration options, so creating a custom wrapper that does exactly what I need certainly helps. As you can see above the parser has a ton of control over how many parsing aspects are handled which is really cool.

The really nice thing though - and the thing that really is missing in my parser - is extensibility. You can create custom Converters that can be plugged into the parsing pipeline to serialize and optionally deserialize custom types. Any JSON parser is likely to do well with most common types, but there may also be custom types or structures that are not supported or not well supported. For example, the ADO.NET objects, or a less obvious problem of how IDictionary types are handled (JSON.NET only supports string keys and then only those that result in valid JavaScript property/map names).

Luckily you can create your own converters, which is a common way of extensibility. The ASP.NET JavaScriptSerializer also supports extension via Converters. So, my immediate need before I could use the JSON.NET parser for a couple of old apps was to create a parser that can serialize JSON from Datatables.

Here's are a few converters that can create DataSet/DataTable and DataRow JSON with JSON.NET and turns them into simple value arrays (ie Dataset.Tables[].Rows[]).  Note the converters are only for serialization not deserialization:

/// <summary>
/// Converts a <see cref="DataRow"/> object to and from JSON.
/// </summary>
public class DataRowConverter : JsonConverter
{
    /// <summary>
    /// Writes the JSON representation of the object.
    /// </summary>
    /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
    /// <param name="value">The value.</param>
    public override void WriteJson(JsonWriter writer, object dataRow)
    {
        DataRow row = dataRow as DataRow;

        // *** HACK: need to use root serializer to write the column value
// should be fixed in next ver of JSON.NET with writer.Serialize(object)
JsonSerializer ser = new JsonSerializer(); writer.WriteStartObject(); foreach (DataColumn column in row.Table.Columns) { writer.WritePropertyName(column.ColumnName); ser.Serialize(writer,row[column]); } writer.WriteEndObject(); } /// <summary> /// Determines whether this instance can convert the specified value type. /// </summary> /// <param name="valueType">Type of the value.</param> /// <returns> /// <c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>. /// </returns> public override bool CanConvert(Type valueType) { return typeof(DataRow).IsAssignableFrom(valueType); } /// <summary> /// Reads the JSON representation of the object. /// </summary> /// <param name="reader">The <see cref="JsonReader"/> to read from.</param> /// <param name="objectType">Type of the object.</param> /// <returns>The object value.</returns> public override object ReadJson(JsonReader reader, Type objectType) { throw new NotImplementedException(); } } /// <summary> /// Converts a DataTable to JSON. Note no support for deserialization /// </summary> public class DataTableConverter : JsonConverter { /// <summary> /// Writes the JSON representation of the object. /// </summary> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="value">The value.</param> public override void WriteJson(JsonWriter writer, object dataTable) { DataTable table = dataTable as DataTable; DataRowConverter converter = new DataRowConverter(); writer.WriteStartObject(); writer.WritePropertyName("Rows"); writer.WriteStartArray(); foreach (DataRow row in table.Rows) { converter.WriteJson(writer, row); } writer.WriteEndArray(); writer.WriteEndObject(); } /// <summary> /// Determines whether this instance can convert the specified value type. /// </summary> /// <param name="valueType">Type of the value.</param> /// <returns> /// <c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>. /// </returns> public override bool CanConvert(Type valueType) { return typeof(DataTable).IsAssignableFrom(valueType); } /// <summary> /// Reads the JSON representation of the object. /// </summary> /// <param name="reader">The <see cref="JsonReader"/> to read from.</param> /// <param name="objectType">Type of the object.</param> /// <returns>The object value.</returns> public override object ReadJson(JsonReader reader, Type objectType) { throw new NotImplementedException(); } } /// <summary> /// Converts a <see cref="DataSet"/> object to JSON. No support for reading. /// </summary> public class DataSetConverter : JsonConverter { /// <summary> /// Writes the JSON representation of the object. /// </summary> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="value">The value.</param> public override void WriteJson(JsonWriter writer, object dataset) { DataSet dataSet = dataset as DataSet; DataTableConverter converter = new DataTableConverter(); writer.WriteStartObject(); writer.WritePropertyName("Tables"); writer.WriteStartArray(); foreach (DataTable table in dataSet.Tables) { converter.WriteJson(writer, table); } writer.WriteEndArray(); writer.WriteEndObject(); } /// <summary> /// Determines whether this instance can convert the specified value type. /// </summary> /// <param name="valueType">Type of the value.</param> /// <returns> /// <c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>. /// </returns> public override bool CanConvert(Type valueType) { return typeof(DataSet).IsAssignableFrom(valueType); } /// <summary> /// Reads the JSON representation of the object. /// </summary> /// <param name="reader">The <see cref="JsonReader"/> to read from.</param> /// <param name="objectType">Type of the object.</param> /// <returns>The object value.</returns> public override object ReadJson(JsonReader reader, Type objectType) { throw new NotImplementedException(); } }

Maybe somebody else will find this useful as well. The serialization is one way only because I personally don't have any need for two-way and deserialization of these objects is tricky because deserialization requires a type to match properties to values in the parsed JSON and well these ADO structures don't have any type format.

Anyway JSON.NET is really nice because it's highly configurable and actively developed. It's also open code so you can look through it and see how its done and tweak if necessary. One thing though - it appears it is a bit slower than other solutions. I've found JSON.NET 2.0 to be more than twice as slow as other solutions, and JSON.NET 3.0 as much as 6 to 7 times slower in some informal iteration tests built into my test suite (I noticed this because tests were slowing down drastically on the perf loop). While processing times are still very small (7 seconds for 10,000 serializations w/ JN 3.0) it still rankles a bit when its considerably slower than other solutions.

DataSet/DataTable/DataRow Serialization in JavaScriptSerializer

The stock JavaScriptSerializer that ships with System.Web.Extensions as part of .NET 3.5 also doesn't directly support ADO.NET objects. Some time ago there was a Converter provided in the Futures package (might still be but I haven't checked) but I never actually used it because the Futures assembly is just too much in flux and you never know what sticks around and will get axed.

Luckily it's also pretty easy to create custom converters for JavaScriptSerializer and so it's easy to create DataSet/Table/Row converters that you can add to your own apps without having to rely on the futures DLL. Here's that same implementation for the JavaScriptSerializer:

internal class WebExtensionsJavaScriptSerializer : JSONSerializerBase, IJSONSerializer
{
    public WebExtensionsJavaScriptSerializer(JSONSerializer serializer) : base(serializer)
    {}
  
    public string Serialize(object value)
    {
        JavaScriptSerializer ser = new JavaScriptSerializer();

        List<JavaScriptConverter> converters = new List<JavaScriptConverter>();

        if (value != null)
        {
            Type type = value.GetType();
            if (type == typeof(DataTable) || type == typeof(DataRow) || type == typeof(DataSet))
            {
                converters.Add(new WebExtensionsDataRowConverter());
                converters.Add(new WebExtensionsDataTableConverter());
                converters.Add(new WebExtensionsDataSetConverter());
            }

            if (converters.Count > 0)
                ser.RegisterConverters(converters);
        }
        
        return = ser.Serialize(value);
    }
    public object Deserialize(string jsonText, Type valueType)
    {
        // *** Have to use Reflection with a 'dynamic' non constant type instance
        JavaScriptSerializer ser = new JavaScriptSerializer();

        
        object result = ser.GetType()
                           .GetMethod("Deserialize")
                           .MakeGenericMethod(valueType)
                          .Invoke(ser, new object[1] { jsonText });
        return result;
    }
}



internal class WebExtensionsDataTableConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new Type[] {typeof (DataTable)}; }
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type,
                                       JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }
 

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        DataTable table = obj as DataTable;

        // *** result 'object'
        Dictionary<string, object> result = new Dictionary<string, object>();

        if (table != null)
        {
            // *** We'll represent rows as an array/listType
            List<object> rows = new List<object>();

            foreach (DataRow row in table.Rows)
            {
                rows.Add(row);  // Rely on DataRowConverter to handle
            }
            result["Rows"] = rows;

            return result;
        }

        return new Dictionary<string, object>();
    }
}

internal class WebExtensionsDataRowConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new Type[] { typeof(DataRow) }; }
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type,
                                       JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        DataRow dataRow = obj as DataRow;
        Dictionary<string, object> propValues = new Dictionary<string, object>();                    

        if (dataRow != null)
        {
            foreach (DataColumn dc in dataRow.Table.Columns)
            {
                propValues.Add( dc.ColumnName, dataRow[dc]);
            }
        }

        return propValues;
    }
}

internal class WebExtensionsDataSetConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new Type[] { typeof(DataSet) }; }
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type,
                                       JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        DataSet dataSet = obj as DataSet;
        Dictionary<string, object> tables = new Dictionary<string, object>();

        if (dataSet != null)
        {
            foreach (DataTable dt in dataSet.Tables)
            {
                tables.Add(dt.TableName, dt);
            }
        }

        return tables;
    }
}

Implementing a custom converter involves creating dictionaries of property name and value pairs with the abillity to create nested properties by specifying another dictionary as a value. This approach is makes it pretty easy to create custom serialization formats...

I know I'm not using DataSets much anymore these days but with older code still sitting around that does these converters are coming in handy. Maybe this will prove useful to some of you in a similar situation.


The Voices of Reason


 

Richard Deeming
September 11, 2008

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

Linq can simplify this code slightly:

// Data Row:
return dataRow.Table.Columns.Cast<DataColumn>().ToDictionary(c => c.ColumnName, c => dataRow[c]);

// Data Table:
return new Dictionary<string, object>
{
    { "Rows", table.Rows },
    { "Columns", table.Columns.Cast<DataColumn>().Select(c => c.ColumnName) }
};

// Data Set:
return dataSet.Tables.Cast<DataTable>().ToDictionary(t => t.TableName, t => (object)t);

karthik
February 23, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

How can i get JSON object? That is JSON representation from a JSON string? using your Library?
Thanks in advance
-karthik

Glen
March 03, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

Perhaps I'm being dense or missing something simple but I am getting a reference error on this line:
json.Converters.Add(new DataRowConverter());
The type or namespace name 'DataRowConverter' could not be found (are you missing a using directive or an assembly reference?)
And all the other ones below it for DataTable and DataSet.

I have downloaded and installed the ASP.NET Futures msi and added that reference to my webservice. I have also modified my web.config according to the documentation as well as adding some stuff I found on the web.

My using statements:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using Newtonsoft.Json;
using System.IO;
using System.Data;
using Microsoft.Web.Preview;

Nothing has worked, I am stumped.

Any ideas?

BTW, I have implemented the same anti-bot scheme as you have (before I saw yours) with the math question and it has worked really well. I haven't had any complaints about the math equation yet. :)

Rick Strahl
March 03, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

@Glen - DataRowConverter is in the code I posted...

Glen
March 03, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

Well that's definitely a forehead smacker :|

This is becoming really frustrating, almost all the examples I've are in C#, if I wanted to program in that style I'd go back to programming java (shiver). When I finally find one that looks like what I need I have to convert it over to VB.

Sigh.

Howard
March 24, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

I need to build a deserializer that takes json text (multiple rows) to a datatable... Is there an easy way to make that happen? Can't find many examples. Your deserializer almost accomplishes this, but I'm not sure how to loop through the object rows. Can you describe how this could be accomplished?

Rick Strahl
April 24, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

@Howard - deserialization of DataSets would be very difficult to do because the way JSON parsing is typically done is based available type information of the type your are deserializing into. IOW, parsers tend to reflect over the properties that the json provides, figure out the type and then assign the value.

DataSets/DataTables/DataRows are untyped so there's no easy way to detect and set the types in the DataRow. You could guess but that's pretty tricky because of the away values are presented and you'd only end up with the few base types that JavaScript supports (string, number, bool and date).

None of the parsers out there support this - it can be done but it probably won't yield the results you're looking for anyway because you'd get none of the persistance/change information that datasets normally provide anyway.

Maulik
June 19, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

Hi Rick,

Thank you for sharing this article with us. I am facing on problem. Can you please help ?
I am serializing and deserializing datatable using JavaScriptSerializer as you explained very last in your post. Now, My datatable having some datetime columns. So, When I deserialize datatable in javascript I am getting datetime in "Thu May 21 17:59:04 UTC+0530 2009" format but I want date time in MM/dd/yyyy HH:MM:SS format. Is there any workaround to do this ?

Thank you,
Maulik

Luka
July 02, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

deserialization .... where exactly is this sample showing custom deserialization.I mena you get this jsonreader object...how the hell can you at least go through the json objects and arrays.
is there any way to load this into some PARSER.
If one can traverse through the crap that you get as a jsonreader as simple as you would an xml file one could EASILY deserialize any object.Including the freaking datatable.
Any help on this?

jono
August 20, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

This is great. 2 things are bugging me though and that is

1) why aren't these converters packaged as part of the JSON.NET library in the first place.

2) I saw somewhere on the web amongst Microsofts ASP sites that you can create classes to represent your rows in the datatable & decorate the properties with something that would make them publishable by the webservice into Json. I can't remember the decoration name, but I think it included the ResponseFormat.Json in the web service. My question is, does MS provide this functionality already without having to use the JSON.NET library? I would have thought that MS would have come up with something since JSON client communication is going to be pretty big...

Rick Strahl
August 20, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

@jono - the main reason I'd guess is because there wouldn't be two way converters. Converting back from JSON into a DataTable is not really possible without type information available not without a whole separate way to parse the JSON anyway - currently all parsers look at the object structure to figure out type info and then read values from the JSON based on that. Since a serialized data table doesn't include data information and a generic data table doesn't have type information the parsing process would have to guess types based on values (not impossible but completely different approach).

jono
August 20, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

Thanks Rick. I guess its upto us as the developers do that bit. S/w development is certainly not getting less complex despite all these fancy new tools & abstraction layers, but I think its actually hiding the fact that people are expecting much more complexity from s/w these days.

David Chell
August 26, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

I use the very old AjaxPro DLL for my JSON Serilaization/Deserialization: e.g.

In Javascript at the client you can create a DotNet Compatible Dataset with:
var ds = new Ajax.Web.DataSet();
var dt = new Ajax.Web.DataTable();
dt.addColumn("TownCityID", "System.Int32");
dt.addColumn("PropertyID", "System.Int32");
dt.addColumn("PackageID", "System.Int32");
dt.addColumn("OrderID", "System.Int32");
ds.addTable(dt);

dr = new Object();
dr.TownCityID = ...;
dr.PropertyID = ...;
dr.PackageID = ...;
dr.OrderID = ...;
dt.addRow(dr);

var hf = document.getElementById("DataSet"); // Get the hidden field to put the JSON into
hf.value = AjaxPro.toJSON(ds);
var form = document.forms[0];
form.submit();

Then you can deserialize it with:

DataSet ds = (DataSet)AjaxPro.JavaScriptDeserializer.DeserializeFromJson(Page.Request.Form["DataSet"], typeof(DataSet));


Or you can create your dataset at the server end in the usual way and serialize it to send it back to the client in a Ajax call:

AjaxPro.DataSetConverter oConverter = new DataSetConverter();
string strJson = oConverter.Serialize(ds);
// Send strJson to the client in whatever way your Ajax library supports.


then create the dataset object in the usual way from the JSON - exact method depends on the Ajax library you're using.

You can also create a dataset from XML:
var ds = Ajax.Web.DataSet(xmlString);


Well that's my two cents worth, I hope you find this info helpful.

Craig
October 06, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

Can anybody point me to an example of this code, or any code that would let me use JSON.NET to serialize a datatable to JSON in a web service, using VB.NET?

Every example uses C#, and there's always some part of code that doesn't translate to VB. The guy who wrote the library obviously has no interest in helping anybody actually use it, that's why this post has been so popular, but here again I run into C# syntax that I can't map to VB.NET.

Obviously SerializeObject didn't work - that would have been too easy - and I'm trying to figure out how to make the JSONSerializer work.

Something else that is obvious is that I could sit here and scour the internet and eventually figure out how to translate all the C# examples into VB. But I'm almost out of time.

I'm just trying to solve a problem and put something to bed. I know I'm totally uncool for using VB and a complete failure as a programmer and a human being. But even loser VB programmers have to make a living, you know? If somebody could just post a quick block showing how to get the datatable serialized to JSON before returning it from a web service, I'm sure Jesus will smile upon you.

James Newton-King
November 21, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

Thanks for the kind words Craig. An attitude like that will get you far in life I'm sure.

Since you're so nice to me I'll give you a tip for whenever you come across C# code. This is the same process I use when I come across an example in VB.NET:

-First I copy the VB.NET/C# into a new Visual Studio project
-I compile the the project
-I open the new compiled dll in Reflector
-And I switch the decompiled code view to my language of choice (VB.NET for you)

Baring any deficiencies in the VB.NET language you now you have a working code example.

Tian guiyuan
December 09, 2009

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

Thanks for this tool by json.net.
I have a question, just like this , I am using the c# .NET framework1.1 to develop, and want to use the JSON data-model to transfer the data between the server and client(but server is developed by Java language). I find none of information about the json for .netframework1.1.
you support json.net's .netframework version is 2.0 or higher. I want to get your help for this question, and thank you very much......

Bart Butell
February 17, 2010

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

I like this interface.
Using your code, how do you deserialize on the client in Javascript?

Jagdish
July 26, 2010

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

I have a json string, How can i convert it to a DataTable using your Class..

Rick Strahl
July 27, 2010

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

Jagdish, If you read the entire article it explains why it doesn't convert the datatable back - the structure doesn't exist. JSON doesn't provide schema info, so you'd have to guess at the structure of the data table. This means something would have to preparse the JSON in order to figure out the DataTable fieldnames first then guessing at the type, and then do an import.

Another way this might be approached is to require that the datatable exists before deserializing and using that structure as an input parameter, but that would also change the typical way the deserialization process works and wouldn't be pluggable anymore.

In short - JSON deserialization is not something that you should attempt. XML with schema info is much better suited for two way conversions (and DataSets/DataTables) natively support this.

yalp
September 16, 2010

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

thanks been looking for this combo.

Ori
November 17, 2010

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

Finally, a desent ado.net types to json serializer, Thank u!
James just added suppot in JSON.NET to typenamehandling, would u recomend using it now to improve the desiraliziton of json back to ado.net types?

John
February 03, 2011

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

when I am data serializition I am getting System.OutOfMemoryException exception. But if I delete some data it is working. How can I serialize big data?

Seven
March 29, 2011

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

You can also try thy this method here: http://codehelp.smartdev.eu/2011/03/29/json-serialization-and-deserialization-in-asp-net-c/. What do you think?

Rick Strahl
March 29, 2011

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

@Seven - JavaScriptSerializer doesn't serialize DataTable/DataSet by default. That's what the code above is about which provides a custom converter so it does.

Elvis
May 19, 2011

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

Sorry to the post I had put in initally --- I figured that out. if anyone wants, the code's below:

for DataRowConverter's WriteJson method:
public override void WriteJson(JsonWriter writer, object dataRow, JsonSerializer serializer)
{
DataRow row = dataRow as DataRow;

// *** HACK: need to use root serializer to write the column value
// should be fixed in next ver of JSON.NET with writer.Serialize(object)
JsonSerializer ser = new JsonSerializer();

writer.WriteStartObject();
for(int i = 1; i < row.Table.Columns.Count; i++)
{
writer.WritePropertyName(row.Table.Columns[i].ColumnName);
ser.Serialize(writer, row[i]);
}
writer.WriteEndObject();
}

for DataTableConverter's WriteJson method:
public override void WriteJson(JsonWriter writer, object dataTable, JsonSerializer serializer)
{
DataTable table = dataTable as DataTable;
DataRowConverter converter = new DataRowConverter();

writer.WriteStartObject();


//writer.WriteStartArray();

foreach (DataRow row in table.Rows)
{
writer.WritePropertyName(row[0].ToString());
converter.WriteJson(writer, row, null);
}

//writer.WriteEndArray();
writer.WriteEndObject();
}

Nelson
March 06, 2012

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer


I have copied all the code to one class and when I try to compile I get the following errors:

______________________________________________________________________
'DataRowConverter' does not implement inherited abstract member 'Newtonsoft.Json.JsonConverter.ReadJson(Newtonsoft.Json.JsonReader, System.Type, object, Newtonsoft.Json.JsonSerializer)'
______________________________________________________________________
Error 4 'DataTableConverter' does not implement inherited abstract member 'Newtonsoft.Json.JsonConverter.CanConvert(System.Type)'

and other errors,

What am I missing?

Thanks in advance (Great article by the way!)

Nelson
March 06, 2012

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer


I figured it out!

Change the ReadJson parameters (In all instances of that function)to look like shown below:

public override object ReadJson(JsonReader reader, Type objectType, Object obj, JsonSerializer serializer)
{
throw new NotImplementedException();
}

Jacob
October 17, 2014

# re: DataTable JSON Serialization in JSON.NET and JavaScriptSerializer

This might help someone in the future, maybe me after I forget what I did.

Made a change to the DataRowConverter to handle rows that are sub-tables. Note that the method uses the newer parameterization, passing the root JsonSerializer.

        public override void WriteJson(JsonWriter writer, object dataRow, JsonSerializer serializer)
        {
            DataRow row = dataRow as DataRow;
 
            //JsonSerializer ser = new JsonSerializer();
 
            writer.WriteStartObject();
            foreach (DataColumn column in row.Table.Columns)
            {
                if (column.GetType() == typeof(DataTable))
                {
                    DataTableConverter converter = new DataTableConverter(json);
                    converter.WriteJson(writer, column, json);
                }
                writer.WritePropertyName(column.ColumnName);
                //ser.Serialize(writer, row[column]);
                json.Serialize(writer, row[column]);
            }
            writer.WriteEndObject();
        }

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024