将数据行转换为JSON对象

14

我有一个DataTable,其中只有一行,看起来像:

   America              |  Africa               |     Japan     |   
   -------------------------------------------------------------
  {"Id":1,"Title":"Ka"} | {"Id":2,"Title":"Sf"} | {"Id":3,"Title":"Ja","Values":{"ValID":4,"Type":"Okinawa"}} 
DataTable的列为美洲、非洲和日本。现在我想将DataTable转换为JSON,使其看起来像:
{
"America": {
    "Id": 1,
    "Title": "Ka"
},
"Africa": {
    "Id": 2,
    "Title": "Sf"
},
"Japan": {
    "Id": 3,
    "Title": "Ja",
    "Values": {
        "ValID": 4,
        "Type": "Okinawa"
    }
  }
}  

我的尝试是:

string js = JSonConvverter.Serializeobject(datatable);
var objType =  JObject.Parse(js);

但它没起作用。感激任何帮助。


请查看Json.NET http://www.newtonsoft.com/json - fabrosell
4个回答

25
假设您正在使用 ,那么有一个特殊的内置转换器 DataTableConverter,它以缩写格式输出数据表,作为行数组,其中每一行都被序列化为列名/值对,如您的问题所示。虽然也有一个用于 DataSet 的转换器,但没有针对 DataRow 的特定内置转换器。因此,当直接序列化 DataRow 时,Json.NET 将序列化 DataRow 的所有字段和属性,导致输出更冗长 - 这不是您想要的。

将DataRow序列化为DataTable使用的更紧凑形式最直接的方法是将整个表格序列化为JArray,然后使用JArray.FromObject()选择与要序列化的DataRow具有相同索引的数组项:

var rowIndex = 0;

var jArray = JArray.FromObject(datatable, JsonSerializer.CreateDefault(new JsonSerializerSettings { /* Add settings as required e.g. */ NullValueHandling = NullValueHandling.Ignore }));

var rowJToken = jArray[rowIndex];
var rowJson = rowJToken.ToString(Formatting.Indented);  // Or Formatting.None if you prefer

由于您的表格只有一行,rowIndex 应该是 0。更一般地,如果您不知道给定 DataRow 的索引,则请参阅 如何从数据表中获取行号?

这对于只有一行的表格应该很好用,但在一般情况下不会很高效。

演示 fiddle #1 在这里

或者,如果表格有许多行但只有少数列,您可以使用 LINQ 将行转换为 Dictionary<string, object>,然后将其序列化:

var rowJson = JsonConvert.SerializeObject(
    row.Table.Columns.Cast<DataColumn>()
        .ToDictionary(c => c.ColumnName, c => row.IsNull(c) ? null : row[c]), 
    Formatting.Indented);

只要列数不多,性能应该不会太差。
Fiddle #2 在这里
将一行序列化为JSON的最高效方式是为 DataRow 引入一个自定义的 JsonConverter ,以将行写入JSON对象:
public class DataRowConverter : JsonConverter<DataRow>
{
    public override DataRow ReadJson(JsonReader reader, Type objectType, DataRow existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException(string.Format("{0} is only implemented for writing.", this));
    }

    public override void WriteJson(JsonWriter writer, DataRow row, JsonSerializer serializer)
    {
        var table = row.Table;
        if (table == null)
            throw new JsonSerializationException("no table");
        var contractResolver = serializer.ContractResolver as DefaultContractResolver;

        writer.WriteStartObject();
        foreach (DataColumn col in row.Table.Columns)
        {
            var value = row[col];

            if (serializer.NullValueHandling == NullValueHandling.Ignore && (value == null || value == DBNull.Value))
                continue;
            
            writer.WritePropertyName(contractResolver != null ? contractResolver.GetResolvedPropertyName(col.ColumnName) : col.ColumnName);
            serializer.Serialize(writer, value);
        }
        writer.WriteEndObject();
    }
}

然后像这样使用:

var settings = new JsonSerializerSettings
{
    Converters = { new DataRowConverter() },
    // Add other settings as required.
};
var rowJson = JsonConvert.SerializeObject(row, Formatting.Indented, settings);

注意:

  • 尽管对单个DataRow进行序列化是有意义的,但对其进行反序列化是没有意义的,因为DataRow不是独立的对象;它只存在于某个父级DataTable中。因此,ReadJson()未实现。

  • JsonConverter<T>在Json.NET 11.0.1中引入。在早期版本中,继承自JsonConverter

演示fiddle #3 在这里


6
作为对于此处所提供的答案 的一种替代方案,你可以使用一个 ExpandoObject 来快速而且相当简单地将单行渲染成JSON,做法如下:
var expando = new System.Dynamic.ExpandoObject() as IDictionary<string, object>;
foreach (DataColumn col in myRow.Table.Columns)
{
    expando[col.ColumnName] = myRow[col];
}
var json = JsonConvert.SerializeObject(expando);

3

拼写错误了吗?你调用 "SerializeObject" 方法的应该是:

string js = JsonConvert.SerializeObject(datatable);

还可以参考一个类似的问题,关于如何使用JSON.NET将datatable转换为JSON字符串


2

像Gazzi所说,您应该包含NewtonSoft.Json库,它已包含在Visual Studio中。

要获得类似于您所描述的对象,您应该创建一个数据模型,例如Country.cs,它将如下所示。

[Serializable]
public class CountryModel {
   public int ID { get; set; }
   public string Title { get; set; }
   public List<ValueModel> Values { get; set; }
}

[Serializable]
public class ValueModel {
   public int ValueID { get; set; }
   public string Type { get; set; }
}

创建一个帮助函数,将您的表格数据转换为这些模型。然后,您可以使用Newtonsoft库根据需要序列化/反序列化数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接