有没有一种简单的方法可以反序列化JSON字符串,而将所有数组都保留为字符串?

时间:2018-08-21 19:05:46

标签: json json.net c#-7.0

基本上我想做的是将一个级别的JSON(最初是顶级)反序列化为ExpandoObject,但是将该级别的所有属性(发现是数组)转换为JSON字符串(而不是将它们递归反序列化为列表)自己的。)

是这样的:

p.x_range.group_padding = 1.0

会生成一个ExpandoObject,它是一个List ,具有一个Int32 Id,字符串名称和String联系人作为属性,在那里,联系人被转换为JSON字符串,如下所示:

[
 {
   "id": 1,
   "name": "one",
   "contacts": [
     { "name": "john", "email":"john@somewhere.com" },
     { "name": "jane", "email":"jane@somewhere.com" }
   ]
 },
 {
   "id": 2,
   "name": "two",
   "contacts": [
     { "name": "jess", "email":"jess@somewhere.com" },
     { "name": "jenn", "email":"jenn@somewhere.com" }
   ]   
 }
]

2 个答案:

答案 0 :(得分:0)

这不是一个常见的用例,因此我不知道对此有任何现有的支持。

我将使用Json.NET的LINQ到JSON,然后在填充ExpandoObject时将所需的内容转换为。这是一个适用于您的示例数据的示例:

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;
using Newtonsoft.Json.Linq;

class Test
{
    static void Main()
    {
        string json = File.ReadAllText("test.json");
        JArray top = JArray.Parse(json);
        var expandos = top
            .Cast<JObject>()
            .Select(ConvertToExpando)
            .ToList<dynamic>();
        Console.WriteLine(expandos[0].id);       // 1 (as an Int64)
        Console.WriteLine(expandos[0].name);     // one
        Console.WriteLine(expandos[0].contacts); // JSON
    }

    static ExpandoObject ConvertToExpando(JObject jobject)
    {
        var expando = new ExpandoObject();
        IDictionary<string, object> dictionary = expando;
        foreach (var pair in jobject)
        {
            dictionary[pair.Key] = ConvertValue(pair.Value);
        }
        return expando;

        object ConvertValue(JToken token)
        {
            switch (token)
            {
                case JArray array:
                    return array.ToString();
                case JValue value:
                    return value.Value;
                default:
                    throw new Exception($"Can't handle {jobject.GetType()} yet");
            }
        }
    }

}

答案 1 :(得分:0)

作为Json.Linq选项的替代方法,如果您不介意一点点开销,则可以让整个反序列化发生,然后遍历每个ExpandoObject作为Dictionary来替换集合属性,例如:

  List<ExpandoObject> expandoList = JsonConvert.DeserializeObject<List<ExpandoObject>>(jsonString, new ExpandoObjectConverter());

  foreach (ExpandoObject expando in expandoList) {
    IDictionary<string, object> expandoDict = expando as IDictionary<string, object>;
    if (expandoDict != null) {
      foreach (KeyValuePair<string, object> kvp in expandoDict) {
        if (typeof(IEnumerable<Object>).IsAssignableFrom(kvp.Value.GetType())) {
          expandoDict[kvp.Key] = JsonConvert.SerializeObject(kvp.Value);
        }
      }
    }
  }