如何从字符串数组创建json字符串中的层次结构?

时间:2017-09-01 11:56:24

标签: c# json linq json.net

我正在尝试为层次结构生成json字符串,如下所示:

Company(select * from Company)
    Department(select * from Department)
        Employee(select * from Employee)

以上每个查询都会返回如下字段:

Company Fields -  (Id,Name,Location)
Department Fields - (Id,Name,CompanyId)
Employee Fields - (Id,Name,DepartmentId)

现在我正在尝试为上面的实体生成JSON字符串,如下所示:

预期输出:

{
  "Id": "",
  "Name": "",
  "Location": "",
  "Department": 
        {
           "Id": "",
           "Name": "",
           "CompanyId": "",
           "Employee" : 
               {
                  "Id": "",
                  "Name": "",
                  "DepartmentId": "", 
               }
        }
}

代码:

public string GetData(Child model,List<Parent> parents)
        {
           var fields = new List<string[]>();
           if (parents != null)
           {
                foreach (var parent in parents)
                {
                        var columns = GetColumns(parent); //returns string[] of columns
                        fields.Add(columns);
                 }
            }
            fields.Add(GetColumns(model));
            string json = JsonConvert.SerializeObject(fields.ToDictionary(key => key, v => string.Empty),
                                        Formatting.Indented);
            return json;
        }

现在,当我没有任何父母,并且想要为唯一的孩子生成json字符串时,下面的代码工作正常:

string json = JsonConvert.SerializeObject(fields.ToDictionary(key => key, v => string.Empty),Formatting.Indented)

输出

{
  "Id": "",
  "Name": "",
  "Location": "",
}

但是现在我想用任何这样的内置方式为我的层次结构生成JSON。

我知道我可以循环,追加和创建json字符串,但我希望以更好的方式做到这一点,就像我为我的孩子所做的那样。

更新:

public class Child
{
    public string Name { get; set; } // Contains Employee
   //Other properties and info related to process sql query and connection string
}


public class Parent
{
    public string Name { get; set; } // Contains Company,Department.
    public string SqlQuery { get; set; } // query related to Company and Department.
    //Other properties and info related to connection string
}

6 个答案:

答案 0 :(得分:2)

也许我错过了什么。如果您在heirachy中创建所需的类,使用数据对它们进行实例化,然后对它们进行序列化,那么将为您创建结构。

using System.Web.Script.Serialization;

public class Employee 
{
   public int Id {get; set; }
   public string Name {get; set; }
   public int DepartmentId {get; set; }   
}

public class Department 
{
   public int Id {get; set; }
   public string Name {get; set; }
   public string CompanyId {get; set; }
   public List<Employee> {get; set;}
}

public class Company {
   public int Id {get; set; }
   public string Name {get; set; }
   public string Location {get; set; }
   public List<Department> {get; set;}
}

var myCompany = new Company();
// add departments and employees

var json = new JavaScriptSerializer().Serialize(myCompany);

答案 1 :(得分:2)

更新:

好的,再试一次。

我创建了一个类,它在子父结构中与您提议的内容类似地保存信息。我还添加了一个递归工作的自定义小分析器。也许这就是你需要什么和/或什么能为你提供解决问题所需的想法。

我还通过添加有角度的括号(“[]”)来稍微改变输出。我想这就是你需要多个孩子的东西。至少那就是JSON验证器告诉我的,我发布在下面。如果您不需要/想要它们,只需在解析器中删除它们。

我不认为你可以使用你在你的例子中使用的解析器,而没有我在之前的答案中显示的某些形式的额外字段,因为那些解析器通常将属性名称作为字段,我想你不想创建类在运行时动态。

我也不认为你可以用Lists,Arrays或Dictionaries创建一个动态深度的亲子 - 孩子......关系,因为这些结构一旦有了设定深度宣布。

希望这会有所帮助。如果没有,请告诉我。

班级:

public class MyJsonObject
{
    public List<string> Columns = new List<string>();

    public string ChildName;
    public List<MyJsonObject> Children = new List<MyJsonObject>(); 
}

分析器:

class JsonParser
{
    public static string Parse(MyJsonObject jsonObject)
    {
        string parse = "{";

        parse += string.Join(",", jsonObject.Columns.Select(column => $"\"{column}\": \"\""));

        if (!string.IsNullOrEmpty(jsonObject.ChildName))
        {
            parse += $",\"{jsonObject.ChildName}\":";

            parse += $"[{string.Join(",", jsonObject.Children.Select(Parse))}]";
        }

        parse += "}";

        return parse;
    }
}

用法:

class Program
{
    static void Main(string[] args)
    {
        MyJsonObject company = new MyJsonObject();
        company.ChildName = "Department";
        company.Columns.Add("Id");
        company.Columns.Add("Name");
        company.Columns.Add("Location");

        MyJsonObject department = new MyJsonObject();
        department.ChildName = "Employee";
        department.Columns.Add("Id");
        department.Columns.Add("Name");
        department.Columns.Add("CompanyId");

        MyJsonObject employee1 = new MyJsonObject();
        employee1.Columns.Add("Id");
        employee1.Columns.Add("Name");
        employee1.Columns.Add("DepartmentId");

        MyJsonObject employee2 = new MyJsonObject();
        employee2.Columns.Add("Id");
        employee2.Columns.Add("Name");
        employee2.Columns.Add("DepartmentId");

        company.Children.Add(department);
        department.Children.Add(employee1);
        department.Children.Add(employee2);

        var json = JsonParser.Parse(company);
    }
}

输出并链接到JSON-Validator:

https://jsonformatter.curiousconcept.com/

{  
   "Id":"",
   "Name":"",
   "Location":"",
   "Department":[
      {  
         "Id":"",
         "Name":"",
         "CompanyId":"",
         "Employee":[
            {  
               "Id":"",
               "Name":"",
               "DepartmentId":""
            },
            {  
               "Id":"",
               "Name":"",
               "DepartmentId":""
            }
         ]
      }
   ]
}

答案 2 :(得分:1)

您可以使用动态

//here your database
dynamic[] company = new object[] { new { Name = "Company1", DepartmentId = 1 }, new { Name = "Company2", DepartmentId = 2 } };
dynamic[] department = new object[] { new { DepartmentId = 1, Name = "Department1" }, new { DepartmentId = 2, Name = "Department2" } };

//select from database
var data = from c in company
    join d in department on c.DepartmentId equals d.DepartmentId
    select new {Name = c.Name, Department = d};

var serialized = JsonConvert.SerializeObject(data);

结果:

[
  {
    "Name": "Company1",
    "Department": {
      "DepartmentId": 1,
      "Name": "Department1"
    }
  },
  {
    "Name": "Company2",
    "Department": {
      "DepartmentId": 2,
      "Name": "Department2"
    }
  }
]

答案 3 :(得分:1)

好的,我们试试吧。首先,因为我理解你的preblem:你有父母和孩子的属性数组,你需要将它转换为json对象。 重点是:

public static ExpandoObject DicTobj(Dictionary<string, object> properties)
        {
            var eo = new ExpandoObject();
            var eoColl = (ICollection<KeyValuePair<string, object>>)eo;

            foreach (var childColumn in properties)
                eoColl.Add(childColumn);

            return eo;
        }

使用动态 ExpandoObject 将字典转换为对象

其他代码很简单:您使用动态类型将所有对象放到一个  并序列化它。

完整代码:

public static Child Child1 { get; set; } = new Child
        {
            Name = "Child1"
        };

        public static Parent Parent1 { get; set; } = new Parent
        {
            Name = "Parent1"
        };

        public static Parent Parent2 { get; set; } = new Parent
        {
            Name = "Parent2"
        };

        private static void Main(string[] args)
        {
            var result = GetData(Child1, new List<Parent> {Parent1, Parent2});
            Console.WriteLine(result);
        }

        /// <summary>
        ///     This is the magic: convert dictionary of properties to object with preperties
        /// </summary>
        public static ExpandoObject DicTobj(Dictionary<string, object> properties)
        {
            var eo = new ExpandoObject();
            var eoColl = (ICollection<KeyValuePair<string, object>>) eo;

            foreach (var childColumn in properties)
                eoColl.Add(childColumn);

            return eo;
        }

        public static string GetData(Child model, List<Parent> parents)
        {
            var childColumns = GetColumns(model);
            dynamic child = DicTobj(childColumns);

            var parentsList = new List<object>();
            foreach (var parent in parents)
            {
                var parentColumns = GetColumns(parent);
                var parentObj = DicTobj(parentColumns);
                parentsList.Add(parentObj);
            }

            child.Parents = parentsList;

            return JsonConvert.SerializeObject(child);
        }


        /// <summary>
        ///     this is STUB method for example
        ///     I change return type from string[] to Dictionary[columnName,ColumnValue], becouse u need not only column names, but
        ///     with it values, i gues. If not, look commented example at the end of this method
        /// </summary>
        public static Dictionary<string, object> GetColumns(object model)
        {
            var result = new Dictionary<string, object>();
            if (model == Child1)
            {
                result.Add("Id", "1");
                result.Add("Name", "Child1");
                result.Add("Location", "SomeLocation");
            }

            if (model == Parent1)
            {
                result.Add("Id", "2");
                result.Add("Name", "Parent1");
                result.Add("SomeProperty1", "SomeValue1");
            }

            if (model == Parent2)
            {
                result.Add("Id", "3");
                result.Add("Name", "Parent1");
                result.Add("SomeProperty3", "SomeValue2");
            }

            //if u have only columNames and dont need values u can do like this
            //var columns = new[] {"Id", "Name", "SomeProperty1"};//this u get from DB
            //return columns.ToDictionary(c => c, c => new object());

            return result;
        }
    }

    public class Child
    {
        public string Name { get; set; } // Contains Employee
        //Other properties and info related to process sql query and connection string
    }

    public class Parent
    {
        public string Name { get; set; } // Contains Company,Department.

        public string SqlQuery { get; set; } // query related to Company and Department.
        //Other properties and info related to connection string
    }

结果输出:

{
  "Id": "1",
  "Name": "Child1",
  "Location": "SomeLocation",
  "Parents": [
    {
      "Id": "2",
      "Name": "Parent1",
      "SomeProperty1": "SomeValue1"
    },
    {
      "Id": "3",
      "Name": "Parent1",
      "SomeProperty3": "SomeValue2"
    }
  ]
}

答案 4 :(得分:1)

即使您没有固定的结构,也可以传递任何类型的对象:

Newtonsoft.Json.JsonConvert.SerializeObject(new yourCustomObject)

使用此功能。

答案 5 :(得分:1)

获得此结果的最佳方式
- 你必须创建一个具有所有类关系的新类。然后使用 Newtonsoft.Json.JsonConvert.SerializeObject(新组织)
让我们创建一个名为organization的新类。添加要在Json中查看的关系。然后使用JsonConvert转换为JSON。
 或者您可以使用以下动态循环

//here your database<br/>
dynamic[] company = new object[] { new { Name = "Company1", DepartmentId = 1 }, new { Name = "Company2", DepartmentId = 2 } };

dynamic [] department = new object [] {new {DepartmentId = 1,Name =&#34; Department1&#34; },new {DepartmentId = 2,Name =&#34; Department2&#34; }};

//select from database<br/>
var data = from c in company
    join d in department on c.DepartmentId equals d.DepartmentId
    select new {Name = c.Name, Department = d};


var serialized = JsonConvert.SerializeObject(data);