将数据行转换为JSON对象
本文关键字:JSON 对象 转换 数据 | 更新日期: 2023-09-27 18:19:44
我有一个DataTable
,它只有一行,看起来像
America | Africa | Japan |
-------------------------------------------------------------
{"Id":1,"Title":"Ka"} | {"Id":2,"Title":"Sf"} | {"Id":3,"Title":"Ja","Values":{"ValID":4,"Type":"Okinawa"}}
DataTable
列为美国、非洲、日本。
现在我想将DataTable
转换为JSON,使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,那么有一个特殊的内置转换器DataTableConverter
,它以行数组的缩写格式输出数据表,其中每一行都序列化为列名/值对,如您的问题所示。虽然DataSet
也有一个转换器,但DataRow
没有特定的内置转换器。因此,当直接序列化DataRow
时,Json.NET将序列化DataRow
的所有字段和属性,从而产生更详细的输出——这是您不希望的。
以DataTable
使用的更紧凑的形式序列化DataRow
最简单的方法是使用JArray.FromObject()
将整个表序列化为JArray
,然后选择与要序列化的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
的索引,请参阅如何从数据表中获取行号。
这应该适用于只有一行的表,但通常不会具有性能。
在这里演示小提琴#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在这里。
序列化行的最高效的方式是为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
不是一个独立的对象;它只存在于某些父CCD_ 22内部。因此CCD_ 23没有被实现。JsonConverter<T>
是在Json.NET 11.0.1中引入的。在早期版本中,继承自JsonConverter
。
演示小提琴#3在这里。
作为这里找到的答案的替代方案,您可以使用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);
拼写?您对"SerializeObject"方法的调用不应该是:吗
string js = JsonConvert.SerializeObject(datatable);
另请参阅关于将数据表转换为JSON字符串的类似问题。
就像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库序列化/反序列化数据。