如何在JSON中为空的DataTable包含列元数据

我正在寻找适当地描述JSON中的列元数据的方法,稍后由Newtonsoft对其进行解析以构建C#DataTable。这样,我希望解决一个DataTable没有行或没有列的a的问题,但是即使我传递一个空表,我也需要使用标签和希望的数据类型来创建列。

标准输入的示例:

{

"BrokerID": "998",

"AccountID": "1313",

"Packages": [

{

"PackageID": 226,

"Amount": 15000,

"Auto_sync": true,

"Color": "BLUE"

},

{

"PackageID": 500,

"Amount": 15000,

"Auto_sync": true,

"Color": "PEACH"

}

]

}

输入表为空的示例:

{

"BrokerID" : "998",

"AccountID" : "1313",

"Packages":[]

}

当我使用解析此内容时JsonConvert.DeserializeObject<DataTable>(params["Packages"]);,没有行,而且显然没有列。我正在寻找一种描述JSON正文中的列元数据的方法。

回答:

DataTableConverter附带Json.Net不输出列的元数据,即使你设置TypeNameHandlingAll。但是,没有什么可以阻止您制作自己的自定义转换器来执行此操作,而是使用该自定义转换器。以下是我根据您的需求拼凑而成的一种:

class CustomDataTableConverter : JsonConverter

{

public override bool CanConvert(Type objectType)

{

return (objectType == typeof(DataTable));

}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)

{

DataTable dt = (DataTable)value;

JObject metaDataObj = new JObject();

foreach (DataColumn col in dt.Columns)

{

metaDataObj.Add(col.ColumnName, col.DataType.AssemblyQualifiedName);

}

JArray rowsArray = new JArray();

rowsArray.Add(metaDataObj);

foreach (DataRow row in dt.Rows)

{

JObject rowDataObj = new JObject();

foreach (DataColumn col in dt.Columns)

{

rowDataObj.Add(col.ColumnName, JToken.FromObject(row[col]));

}

rowsArray.Add(rowDataObj);

}

rowsArray.WriteTo(writer);

}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)

{

JArray rowsArray = JArray.Load(reader);

JObject metaDataObj = (JObject)rowsArray.First();

DataTable dt = new DataTable();

foreach (JProperty prop in metaDataObj.Properties())

{

dt.Columns.Add(prop.Name, Type.GetType((string)prop.Value, throwOnError: true));

}

foreach (JObject rowDataObj in rowsArray.Skip(1))

{

DataRow row = dt.NewRow();

foreach (DataColumn col in dt.Columns)

{

if (rowDataObj[col.ColumnName].Type != JTokenType.Null)//Skip if the Value is Null/Missing, especially for a non-nullable type.

row[col] = rowDataObj[col.ColumnName].ToObject(col.DataType);

}

dt.Rows.Add(row);

}

return dt;

}

}

这是一个演示。请注意,序列化表时,列类型被写为JSON中数组的第一行。反序列化时,即使没有其他行,此元数据也将用于使用正确的列类型和名称重建表。(您可以通过在顶部将行数据添加到表中的两行注释掉来验证这一点。)

class Program

{

static void Main(string[] args)

{

DataTable dt = new DataTable();

dt.Columns.Add("PackageID", typeof(int));

dt.Columns.Add("Amount", typeof(int));

dt.Columns.Add("Auto_sync", typeof(bool));

dt.Columns.Add("Color", typeof(string));

// Comment out these two lines to see the table with no data.

// Test with a null Value for a Non-Nullable DataType.

dt.Rows.Add(new object[] { 226, null, true, "BLUE" });

dt.Rows.Add(new object[] { 500, 15000, true, "PEACH" });

Foo foo = new Foo

{

BrokerID = "998",

AccountID = "1313",

Packages = dt

};

JsonSerializerSettings settings = new JsonSerializerSettings();

settings.Converters.Add(new CustomDataTableConverter());

settings.Formatting = Formatting.Indented;

string json = JsonConvert.SerializeObject(foo, settings);

Console.WriteLine(json);

Console.WriteLine();

Foo foo2 = JsonConvert.DeserializeObject<Foo>(json, settings);

Console.WriteLine("BrokerID: " + foo2.BrokerID);

Console.WriteLine("AccountID: " + foo2.AccountID);

Console.WriteLine("Packages table:");

Console.WriteLine(" " + string.Join(", ",

foo2.Packages.Columns

.Cast<DataColumn>()

.Select(c => c.ColumnName + " (" + c.DataType.Name + ")")));

foreach (DataRow row in foo2.Packages.Rows)

{

Console.WriteLine(" " + string.Join(", ", row.ItemArray

.Select(v => v != null ? v.ToString() : "(null)")));

}

}

}

class Foo

{

public string BrokerID { get; set; }

public string AccountID { get; set; }

public DataTable Packages { get; set; }

}

输出:

{

"BrokerID": "998",

"AccountID": "1313",

"Packages": [

{

"PackageID": "System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",

"Amount": "System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",

"Auto_sync": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",

"Color": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

},

{

"PackageID": 226,

"Amount": null,

"Auto_sync": true,

"Color": "BLUE"

},

{

"PackageID": 500,

"Amount": 15000,

"Auto_sync": true,

"Color": "PEACH"

}

]

}

BrokerID: 998

AccountID: 1313

Packages table:

PackageID (Int32), Amount (Int32), Auto_sync (Boolean), Color (String)

226, , True, BLUE

500, 15000, True, PEACH

小提琴:https :

//dotnetfiddle.net/GGrn9z

以上是 如何在JSON中为空的DataTable包含列元数据 的全部内容, 来源链接: utcz.com/qa/409695.html

回到顶部