【问题标题】:Is there an easy way to deserialize a JSON string leaving all arrays as strings?有没有一种简单的方法来反序列化 JSON 字符串,将所有数组都保留为字符串?
【发布时间】:2018-08-21 19:05:46
【问题描述】:

基本上我想做的只是将一个级别的 JSON(最初是顶部)反序列化为 ExpandoObject,但将该级别的所有属性(发现是数组)转换为 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" }
   ]   
 }
]

将生成一个 ExpandoObject,它是一个 List,具有 Int32 Id、字符串名称和字符串联系人作为属性,其中联系人被转换为 JSON 字符串,如下所示:

"[{\"name\":\"john\","email\":\"john@somewhere.com\"},{\"name\":\"jane\",\"email\":\"jane@somewhere.com\"}]"

【问题讨论】:

  • 您能否提供一个 JSON 示例,您希望发生什么以及实际发生了什么?听起来您不太可能特别轻松地做到这一点,部分原因是这听起来像是一个不寻常的用例。
  • 我在原帖中添加了一个例子。我意识到这是一个高度专业化的案例,但我在报告引擎中处理了一些非常粗略的约束。我正在为其编写自定义数据提供程序。
  • 我可能会将其解析为JObject,并以此构建您的ExpandoObject。您可能会丢失数组表示中的空格方面的一些细节,但这可能没关系。我会写一个例子...
  • 我注意到你的 JSON 实际上是一个数组作为外部部分,所以我假设你想要一个 List<ExpandoObject>...

标签: json json.net c#-7.0


【解决方案1】:

这不是一个常见的用例,所以据我所知,没有现有的支持。

我会使用 Json.NET 的 LINQ to 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");
            }
        }
    }

}

【讨论】:

    【解决方案2】:

    作为 Json.Linq 选项的替代方案,如果您不介意一点开销,您可以让整个反序列化发生,然后循环遍历每个 ExpandoObject 作为字典来替换集合属性,如下所示:

      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);
            }
          }
        }
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 2012-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多