【问题标题】:Convert complex JSON to Generic List using Newtonsoft使用 Newtonsoft 将复杂的 JSON 转换为通用列表
【发布时间】:2018-12-12 09:37:09
【问题描述】:

下面是一个Json:

[{
    "Result": {
        "description": "Application Security Supp Specialist",
        "code": "40000003"
    }
}, {
    "Result": {
        "description": "Gvt Cyber Intelligence Specialist",
        "code": "40001416"
    }
}, {
    "Result": {
        "description": "Gvt Record Retention Specialist",
        "code": "40001428"
    }
}]

下面是我创建的类结构,因为我需要将其填充到 C# 对象中。 我正在尝试创建 RulesEngineOutput 的集合并用 json 内容填充它。

public class RulesEngineOutput
{
    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("code")]
    public string Code { get; set; }
}

public class RulesEngineOutputCollection
{
    public IEnumerable<RulesEngineOutput> ProbableRoles { get; set; }
}

我正在尝试使用以下代码实现此目的:

var bodyJson = JsonConvert.SerializeObject(bodyString);
RulesEngineOutputCollection result = new RulesEngineOutputCollection();
foreach (var item in bodyJson)
{
    result = JsonConvert.DeserializeObject<RulesEngineOutputCollection>(item.ToString()); 
}

但是当项目获得一个字符时,这会引发异常,我认为我需要在循环中传递一个 JSON 对象,但我无法得到一个。 每次我得到的是一个 JSON 字符串。

无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型“RulesEngineOutputCollection”,因为该类型需要 JSON 对象(例如 {\"name\":\"value\"})才能正确反序列化.\r\n要修复此错误,请将 JSON 更改为 JSON 对象(例如 {\"name\":\"value\"})或将反序列化类型更改为数组或实现集合接口的类型(例如ICollection, IList) 之类的可以从 JSON 数组反序列化的 List。

【问题讨论】:

  • 请发布您的错误消息的确切措辞。指定引发异常的代码行。
  • ProbableRoles 应该被称为(或有JsonProperty)“结果”
  • 是的,您的 DTO 看起来不太正确。您可以将您的 JSON 插入 json2csharp.com 进行验证。
  • 等等。 bodyString 是什么?从它的声音来看,这包含您的 JSON。为什么要连载它?然后尝试遍历那个字符串??
  • Robert -- 这是我收到的错误消息Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'RulesEngineOutputCollection' because the type requires a JSON object (e.g. {\"name\":\"value\"}) to deserialize correctly.\r\nTo fix this error either change the JSON to a JSON object (e.g. {\"name\":\"value\"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List&lt;T&gt; that can be deserialized from a JSON array.

标签: c# .net json json.net jobjectformatter


【解决方案1】:

问题是您的RulesEngineOutput 和您的集合之间有一个中间对象。你需要像这样重组你的对象:

public class RulesEngineOutput
{
    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("code")]
    public string Code { get; set; }
}

public class RulesEngineOutputResult
{
    public RulesEngineOutput Result { get; set; }
}

public class RulesEngineOutputCollection
{
    public IEnumerable<RulesEngineOutputResult> ProbableRoles { get; set; }
}

然后,当您完成此重组后,您可以直接反序列化到您的 RulesEngineOutputCollection,而不是一个对象并再次迭代和反序列化。

result = JsonConvert.DeserializeObject<RulesEngineOutputCollection>(bodyString); 

【讨论】:

    【解决方案2】:

    非常感谢 Max、Nathan 和其他人。所以最后我对代码做了一些修改,下面是我修改的代码:

     var jToken = JObject.Parse(responseContent);
            var bodyString = jToken.SelectToken("body");
            var bodyJson = JsonConvert.SerializeObject(bodyString);
    
    
            List<RulesEngineOutput> result = new List<RulesEngineOutput>();
    
    
            try
            {
    
                foreach (var item in bodyString)
                {
                    var formattedItem = item.SelectToken("Result");
                    var  resultItem = JsonConvert.DeserializeObject<RulesEngineOutput>(formattedItem.ToString());
                       result.Add(resultItem);
                }
    
    
            }
    

    希望它也对其他人有所帮助。

    【讨论】:

      【解决方案3】:

      正如 Nathan Werry 所说,您将一个对象分层到另一个对象中,因此,您无法以您想要的方式反序列化数据。但是,如果您首先创建这些结果的数组并稍后将其分配给您的 ProbableRoles 属性,则可以解决此问题:

      var rules = new RulesEngineOutputCollection
      {
          ProbableRoles = JsonConvert.DeserializeObject<Result[]>(bodyString).Select(r => r.Data).ToList()
      };
      
      public class Result
      {
          [JsonProperty("Result")]
          public RulesEngineOutput Data { get; set; }
      }
      

      其他一切都保持不变。您基本上从结果数组中创建了一个新列表。我也可以直接分配Select() 结果(无需调用.ToList()),但这可以确保对象实际上具有数据,而不仅仅是对枚举的引用。

      【讨论】:

        猜你喜欢
        • 2019-12-13
        • 2020-10-27
        • 2022-01-23
        • 1970-01-01
        • 2012-12-28
        • 2023-01-17
        • 2022-07-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多