首页 > 解决方案 > 使用 Json.NET 反序列化为 DataTable,同时将嵌套令牌保留为 JSON

问题描述

我正在做一个简单的

JsonConvert.DeserializeObject<DataTable>(result.ToString());

源 JSON 可能有嵌套对象。转换器创建嵌套数据表。我只想将根对象转换为 DataTable,并将嵌套对象存储到字符串列中。那可能吗?我看过JsonSerializerSettings但我似乎没有看到相关的设置。

我可以稍后重新序列化嵌套的 DataTable,但这需要更多的处理,并且一些嵌套对象并不一致,我最终会ArgumentException在反序列化期间得到一个。

标签: c#json.net

解决方案


您将需要一个自定义 DataTable 转换器来完成此操作。我改编了这个答案

主要思想是检测属性是否包含带有if (rowDataObj[col.ColumnName].Type == JTokenType.Array). 在这种情况下,我们只需使用.ToString()以保留原始字符串。

class Program
{
    static void Main(string[] args)
    {
        var json = @"[{""Name"":""John"",""Age"":""22"",""Json"":[{""Prop"":1}]},"
                  + @"{""Name"":""Eric"",""Age"":""25"",""Json"":[{""Prop"":2}]},"
                  + @"{""Name"":""Joan"",""Age"":""38"",""Json"":[{""Prop"":3}]}]";
        var table = JsonConvert.DeserializeObject<DataTable>(json, 
            new CustomDataTableConverter());

        foreach (DataRow row in table.Rows)
        {
            Console.WriteLine($"{row["Name"]}, {row["Age"]}, {row["Json"]}");
        }
    }
}

public class CustomDataTableConverter : JsonConverter
{
    public override bool CanConvert(Type objectType) => (objectType == typeof(DataTable));
    public override bool CanWrite => false;

    public override object ReadJson(JsonReader reader, Type objectType, 
        object existingValue, JsonSerializer serializer)
    {
        var rowsArray = JArray.Load(reader);
        var metaDataObj = (JObject)rowsArray.First();
        var dt = new DataTable();

        foreach (var prop in metaDataObj.Properties())
        {
            dt.Columns.Add(prop.Name);
        }
        foreach (JObject rowDataObj in rowsArray)
        {
            var row = dt.NewRow();
            foreach (DataColumn col in dt.Columns)
            {
                if (rowDataObj[col.ColumnName].Type == JTokenType.Array)
                {
                    row[col] = rowDataObj[col.ColumnName].ToString(Formatting.None);
                }
                else
                {
                    row[col] = rowDataObj[col.ColumnName].ToObject(col.DataType);
                }
            }
            dt.Rows.Add(row);
        }
        return dt;
    }

    public override void WriteJson(JsonWriter writer, object value, 
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

结果是:

John, 22, [{"Prop":1}]
Eric, 25, [{"Prop":2}]
Joan, 38, [{"Prop":3}]

推荐阅读