【问题标题】:Convert Dictionary to c# object将字典转换为 c# 对象
【发布时间】:2021-06-06 16:06:41
【问题描述】:

我有一个嵌套字典对象输出,如下所示

{
"name":"test",
"id":1,
"parent": {
      "name":"test1",
      "id":2,
      "parent":{
           "name":"test2",
           "id":3,
            "parent":{
                "name":"test3",
                "id":4,
                "parent":{
                    ....
                      }
                }
            }
      }
}

这里是返回字典对象的代码:

class GetData
{
    public HttpWebResponse WebResponse { get; private set; }
    public Dictionary<string, object> Data { get; private set; }

    public GetData(HttpWebResponse webResponse, Dictionary<string, object> data)
    {
        WebResponse = webResponse;
        Data = data;
    }
}

我有一个包含上述响应的对象,如下所示:

var responseData = GetResponseData(req);

现在我想将上面的字典对象转换为 c# 对象。以下是我的c#对象

class SomeClass
{
    public int Id { get; }
    public string Name { get; }
    public SomeClass Parent { get; }
    
    public IEnumerable<SomeClass> GetAncestry()
    {
        if (Parent is not null)
        {
            yield return Parent;
            foreach (var ancestor in Parent.GetAncestry()) yield return ancestor;
        }
    }
}

我正在尝试以下方法将我的字典对象转换为“SomeClass”对象,但它对我不起作用。有人可以帮我解决吗?

List<SomeClass> smClass = new List<SomeClass>(responseData .Values);

【问题讨论】:

  • GetData 是类的可怕名称
  • 您发布的是 JSON 字符串,而不是字典。您发布的内容不执行任何类型的 JSON 解析。 GetData 类不返回任何内容,它只是将构造函数参数公开为属性。
  • 你为什么使用 Object 的字典而不是类型化的字典。听起来你对架构有误解,你应该描述你正在尝试做的事情,而不是你想要的解决方案
  • 将我的字典对象转换为SomeClass对象 为什么要创建一个列表然后List&lt;SomeClass&gt;(responseData .Values)
  • 你试过反序列化这个 JSON 字符串吗?例如JsonConvert.DeserializeObject&lt;SomeClass&gt;(json)。不需要GetData 类或Dictionary&lt;string,object&gt;

标签: c# asp.net .net model-view-controller c#-4.0


【解决方案1】:

尝试创建结构(或类),例如:

public class NamedObject
{
    int id {get; set;}
    string name {get; set;}
    NamedObject parent {get; set;}
}

然后你可以通过Newtonsoft.Json.JsonConvert.DeserializeObject反序列化你的json(你需要Newtonsoft.Json库或者NuGet包)

NamedObject namedObject = JsonConvert.DeserializeObject<NamedObject>(json);

工作示例(来自您之前的 question):

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

namespace ConsoleApp1
{
    internal class Program
    {

        private static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            string s = "{ \"name\":\"test\", \"id\":1, \"parent\": { \"name\":\"test1\", \"id\":2, \"parent\":{ \"name\":\"test2\", \"id\":3, \"parent\":{ \"name\":\"test3\", \"id\":4, \"parent\": null } } } }";
            TreeNode node = JsonConvert.DeserializeObject<TreeNode>(s);
        }
    }

    public class TreeNode
    {
        [JsonProperty("name")]
        public string Name { get; set; }
        [JsonProperty("id")]
        public int ID { get; set; }
        public NodeType Type { get; }
        public Dictionary<TreeNode, NodeType> Childern { get; }
        public TreeNode GetChildernByName(string name) => Childern.First(x => x.Key.Name == name).Key;
        [JsonProperty("parent")]
        public TreeNode Parent { get; private set; }
        public string FullName => IsRoot ? string.Empty : this.Parent.FullName + "/" + Name;
        public TreeNode(string name, NodeType type, TreeNode parent)
        {
            this.Name = name;
            this.Type = type;
            this.Parent = parent;
            this.Childern = new Dictionary<TreeNode, NodeType>();
        }
        public TreeNode()
        {

        }
        public TreeNode(string name) : this(name, NodeType.Folder, null) { }
        public TreeNode(string name, NodeType type) : this(name, type, null) { }
        public bool IsRoot => Parent == null;
        public void AddChild(params TreeNode[] nodes) => AddChild(true, nodes);
        public void AddChild(bool setParent, params TreeNode[] nodes)
        {
            foreach (TreeNode node in nodes)
            {
                Childern.Add(node, node.Type);
                if (setParent) node.Parent = this;
            }
        }
        public IEnumerable<TreeNode> GetFullPath()
        {
            List<TreeNode> parents = new List<TreeNode>();
            if (this.Parent != null)
            {
                parents.AddRange(Parent.GetFullPath());
            }
            parents.Add(this);
            return parents;
        }
        public override string ToString() => Name;
    }
    public enum NodeType
    {
        Folder,
        File
    }
}

您可以为公共字段使用与 json 中相同的名称,也可以在需要的地方设置 JsonProperty 属性。只记得,你必须有没有参数的构造函数,我建议使用可为空的类型(例如 int?)

【讨论】:

  • 公共字段不是属性。属性是类接口的一部分,字段总是被视为实现细节,无论是否公开
  • @PanagiotisKanavos 谢谢,我错过了。已更正。
  • 你也不需要JsonProperty,JSON.NET默认使用camel-case
  • 也只是一个快速观察,NamedObject namedObject = JsonConvert.DeserializeObject(json); 应该是 NamedObject namedObject = JsonConvert.DeserializeObject&lt;NamedObject&gt;(json);
  • @PanagiotisKanavos,这对我来说是新观点,我只在一个项目中使用 json 并且我有驼峰式名称,所以我从不详细处理这个问题。我只知道名称不匹配时有 JsonProperty。
猜你喜欢
  • 2018-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-04
  • 2019-05-28
  • 1970-01-01
  • 1970-01-01
  • 2011-11-26
相关资源
最近更新 更多