使用Newtonsoft自定义JSON字符串输出

时间:2015-04-30 02:02:31

标签: c# json.net

我尝试使用Newtonsoft JsonConverter序列化C#DataTable

代码:

v

我得到的结果是:

JsonConvert.SerializeObject(dt); //dt is DataTable

我想要的结果是:

[
  {
    "Name": "Tiger Nixon",
    "Position": "System Architect",
    "Address": "Edinburgh",
    "No": "5421"
  },
  {
    "Name": "Garrett Winters",
    "Position": "Accountant",
    "Address": "Tokyo",
    "No": "8422"
  }
]

是否可以使用Newtonsoft自定义输出?我尝试使用{ "data": [ [ "Tiger Nixon", "System Architect", "Edinburgh", "5421" ], [ "Garrett Winters", "Accountant", "Tokyo", "8422" ] ] } 上的foreach编写自己的代码来序列化DataTable,但与Newtonsoft相比,性能是昼夜。

任何帮助将不胜感激

3 个答案:

答案 0 :(得分:6)

您可以使用以下JsonConverter

执行此操作
public class DataTableTo2dArrayConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(DataTable).IsAssignableFrom(objectType);
    }

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

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var table = (DataTable)value;
        var array2d = table.AsEnumerable().Select(row => table.Columns.Cast<DataColumn>().Select(col => row[col]));
        serializer.Serialize(writer, new { data = array2d });
    }
}

然后使用它:

        var settings = new JsonSerializerSettings();
        settings.Converters.Add(new DataTableTo2dArrayConverter());
        var json = JsonConvert.SerializeObject(dt, Formatting.Indented, settings);

请注意,我对System.Data.DataTableExtensions.AsEnumerable()的使用需要引用System.Data.DataSetExtensions.dll

答案 1 :(得分:3)

在我阅读JasonWilczak提供的链接后我是怎么做到的

public class JqueryDatatablesConverter : JsonConverter
{

    public override bool CanConvert(Type objectType)
    {
        return typeof(DataTable).IsAssignableFrom(objectType);
    }

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

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        dynamic dt = (DataTable)value;
        dynamic count = dt.Columns.Count - 1;

        writer.WriteStartObject();
        writer.WritePropertyName("data");
        writer.WriteStartArray();

        foreach (DataRow dr in dt.Rows) {
            writer.WriteStartArray();
            for (int x = 0; x <= count; x++) {
                serializer.Serialize(writer, dr[x]);
            }
            writer.WriteEndArray();
        }

        writer.WriteEndArray();
        writer.WriteEndObject();

    }
}

答案 2 :(得分:2)

这是a working fiddle that demonstrates it。有关详细信息,请参阅the Newtonsoft documentation on Custom JsonConverter

DataTableJsonConverter

DataTable转换为自定义JSON字符串。

public class DataTableJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter w, object v, JsonSerializer s)
    {
        w.WriteStartObject();
        w.WritePropertyName("data");
        w.WriteStartArray();
        foreach(DataRow r in (v as DataTable).Rows)
        {
            w.WriteStartArray();
            foreach(var c in r.ItemArray)
            {
                w.WriteValue(c);
            }
            w.WriteEndArray();
        }
        w.WriteEndArray();
        w.WriteEndObject();
    }

    public override object ReadJson(JsonReader r, Type t, object v, JsonSerializer s)
    {
        throw new NotImplementedException("Unnecessary: CanRead is false.");
    }

    public override bool CanRead { get { return false; } }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DataTable);
    }
}

以下是如何使用

public class Program
{
    public static void Main()
    {
        var dt = SeedData();

        var json = JsonConvert.SerializeObject(
                dt, Newtonsoft.Json.Formatting.Indented,
                new DataTableJsonConverter());

        Console.WriteLine(json);
    }

    public static DataTable SeedData()
    {
        var dt = new DataTable();
        dt.Columns.Add("Name");
        dt.Columns.Add("Position");
        for (var i = 0; i < 2; ++i)
        {
            dt.Rows.Add(new object[] { "Shaun", "Developer" });
        }
        return dt;
    }
}

这是它的输出

{
  "data": [
    [
      "Shaun",
      "Developer"
    ],
    [
      "Shaun",
      "Developer"
    ]
  ]
}

性能

对于那些感兴趣的人,这里有a fork of the fiddle that tries to show the performance三种不同的方法来自我,dbc和 warheat1990超过1500个数据行和两个每个运行。它们都非常接近,由于我不知道的原因,第二次运行总是更快。

DataTableJsonConverter:6 ms
DataTableJsonConverter:2 ms
DataTableTo2dArrayConverter:251 ms
DataTableTo2dArrayConverter:11 ms
JqueryDatatablesConverter:1580 ms
JqueryDatatablesConverter:16 ms