【问题标题】:Parsing JSON Object with variable properties into strongly typed object将具有可变属性的 JSON 对象解析为强类型对象
【发布时间】:2015-12-10 12:56:12
【问题描述】:
{
"Profile": {
    "dProperty1": {
        "a": "value",
        "b": "value",
        "c": "value",
        "d": "value",
        "e": "value"
    },
    "dProperty2": {
        "a": "value",
        "b": "value",
        "d": "value",
        "e": "value"
    },
    "dProperty3": {
        "a": "value",
        "b": "value",
        "d": "value",
        "e": "value"
       }
    }
}

我有一个 JSON 对象,它可以有任意数量的动态属性。所有属性都是主要由相同字段组成的对象。如何在 C# 中将此 JSON 解析为强类型对象?

【问题讨论】:

  • 他们会一直保持同一个名字吗?这有点“不干净”,但过去我创建了一个类,其中包含不同变体的所有可能属性,但 JSON 可能没有所有这些属性。它只是忽略了类中在 JSON 中没有对应的属性。
  • 创建具有所有可能属性的类型并将 JSON 解散到它。
  • 您可以将 Profile 反序列化为 Dictionary (其中 AbcdeClass 包含来自 JSON 的属性的叠加),例如这里 stackoverflow.com/questions/20727787/…

标签: c# json parsing json.net


【解决方案1】:

如果你必须有强类型的结果,我会将 Profile 反序列化为属性叠加的字典

class AbscdeClass
{
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
    public string D { get; set; }
    public string E { get; set; }
}

class JsonBody
{
    public Dictionary<string, AbscdeClass> Profile { get; set; }
}

并将原始 JSON 文本解析为

JsonBody json = JsonConvert.DeserializeObject<JsonBody>(jsonString);

【讨论】:

  • 你说如果我“必须”。你推荐另一种方式吗?
  • 您可以使用动态类型(如@Jon Skeet 的回答)。在您的示例中,我会使用静态类型的字典。如果叠加类变得太大且无结构,或者如果属性列表可以迅速演变,我会做动力学。由于您明确声明您需要静态类型,因此这种推理是不必要的
  • @Igor:我没有使用动态类型。我正在解析为JObject,但我没有在任何地方使用动态输入,而且我仍然有一个静态类型的字典作为值......并不是说你的方法有什么问题,请注意你。
  • @Jon Skeet。我的错 - 我对 JObject 的存在反应太快了。 JObject.Parse的动态使用示例可以在stackoverflow.com/a/9326146/2413030找到
【解决方案2】:

我会将整个树解析为JObject,然后在适当的子对象上调用ToObject&lt;&gt;。示例代码:

using System;
using System.IO;
using System.Linq;
using Newtonsoft.Json.Linq;

class Example
{
    public string Name { get; set; }
    public int Age { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var json = File.ReadAllText("test.json");
        var root = JObject.Parse(json);        
        var profile = (JObject) root["Profile"];
        var map = profile.Properties()
                         .ToDictionary(p => p.Name, p => p.Value.ToObject<Example>());
        foreach (var entry in map)
        {
            Console.WriteLine($"Key: {entry.Key}; Name: {entry.Value.Name}; Age: {entry.Value.Age}");
        }
    }
}

JSON:

{
  "Profile": {
    "dProperty1": {
      "name": "First",
      "age": 30,
      "extra": "Ignored"
    },
    "dProperty2": {
      "name": "Second",
      "age": 25
    },
    "dProperty3": {
      "name": "Third",
      "age": 50
    }
  }
}

结果:

Key: dProperty1; Name: First; Age: 30
Key: dProperty2; Name: Second; Age: 25
Key: dProperty3; Name: Third; Age: 50

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多