【问题标题】:Deserialize to DataTable with Json.NET while keeping nested tokens as JSON使用 Json.NET 反序列化为 DataTable,同时将嵌套令牌保留为 JSON
【发布时间】:2019-07-24 14:59:26
【问题描述】:

我在做一个简单的

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

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

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

【问题讨论】:

    标签: c# json.net


    【解决方案1】:

    您将需要一个自定义 DataTable 转换器来完成此操作。我改编了this answer中的那个。

    主要思路是检测属性是否包含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}]
    

    【讨论】:

      猜你喜欢
      • 2023-03-22
      • 2020-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多