c# - ¿Cómo crear una jerarquía en cadena JSON desde una matriz de cadenas?
linq json.net (6)
Estoy tratando de generar json cadena para la jerarquía como a continuación:
Company(select * from Company)
Department(select * from Department)
Employee(select * from Employee)
Cada una de las consultas anteriores devolverá campos como a continuación:
Company Fields - (Id,Name,Location)
Department Fields - (Id,Name,CompanyId)
Employee Fields - (Id,Name,DepartmentId)
Ahora estoy intentando generar cadena JSON para las entidades anteriores como a continuación:
Rendimiento esperado:
{
"Id": "",
"Name": "",
"Location": "",
"Department":
{
"Id": "",
"Name": "",
"CompanyId": "",
"Employee" :
{
"Id": "",
"Name": "",
"DepartmentId": "",
}
}
}
Código:
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;
}
Ahora, cuando no tengo padres y quiero generar json string para hijo único, el siguiente código funciona bien:
string json = JsonConvert.SerializeObject(fields.ToDictionary(key => key, v => string.Empty),Formatting.Indented)
Salida:
{
"Id": "",
"Name": "",
"Location": "",
}
Pero ahora quiero generar JSON para mi jerarquía de cualquier forma incorporada.
Sé que puedo iterar, anexar y crear json, pero quiero hacerlo de una manera mejor, como lo hice con mi hijo.
Actualizar:
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
}
Puedes usar dynamic :
//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);
resultado:
[
{
"Name": "Company1",
"Department": {
"DepartmentId": 1,
"Name": "Department1"
}
},
{
"Name": "Company2",
"Department": {
"DepartmentId": 2,
"Name": "Department2"
}
}
]
Quizás me estoy perdiendo algo. Si crea las clases que necesita en la heiraquía, las crea con datos y las serializa, la estructura se creará para usted.
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);
Ok, intentemos así. En primer lugar, como entiendo tu problema: tienes matrices de propiedades de padres e hijos y tú, nenet, para convertirlo en objeto json. El punto está aquí:
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;
}
U usa Dynamic y ExpandoObject para convertir diccionario a objeto
El otro código es trivial: puedes poner todos tus objetos en uno usando el tipo dinámico y serializarlo.
El código completo:
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
}
Y resultado de salida:
{
"Id": "1",
"Name": "Child1",
"Location": "SomeLocation",
"Parents": [
{
"Id": "2",
"Name": "Parent1",
"SomeProperty1": "SomeValue1"
},
{
"Id": "3",
"Name": "Parent1",
"SomeProperty3": "SomeValue2"
}
]
}
ACTUALIZADO:
Ok, otro intento.
Creé una clase que contiene la información de manera similar a lo que usted propuso, en una estructura padre-hijo. También agregué un pequeño analizador personalizado que funciona recursivamente. Tal vez eso es lo que necesita y / o lo que le da las ideas que necesita para solucionar su problema.
También modifiqué un poco la salida, agregando los corchetes en ángulo ("[]"). Creo que eso es lo que necesitarás con varios niños. Al menos eso es lo que el validador JSON me dice que publiqué a continuación. Si no los necesita ni los quiere, simplemente elimínelos en el analizador.
No creo que puedas usar el analizador que usaste en tu ejemplo sin tener algún tipo de campo adicional como el que mostré en mi respuesta anterior, ya que esos analizadores usualmente buscan nombres de propiedades como campos y supongo que no deseas crear clases dinámicamente durante el tiempo de ejecución .
Tampoco creo que sea posible para usted crear una profundidad dinámica de su relación padre-hijo-hijo-hijo ... con listas, matrices o diccionarios, porque esas estructuras tienen una profundidad determinada tan pronto como se declaran.
Espero que esto ayude. Si no, házmelo saber.
Clase:
public class MyJsonObject
{
public List<string> Columns = new List<string>();
public string ChildName;
public List<MyJsonObject> Children = new List<MyJsonObject>();
}
Parser:
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;
}
}
Uso:
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);
}
}
Salida y enlace a JSON-Validator:
https://jsonformatter.curiousconcept.com/
{
"Id":"",
"Name":"",
"Location":"",
"Department":[
{
"Id":"",
"Name":"",
"CompanyId":"",
"Employee":[
{
"Id":"",
"Name":"",
"DepartmentId":""
},
{
"Id":"",
"Name":"",
"DepartmentId":""
}
]
}
]
}
Puede pasar cualquier tipo de objeto incluso si no tiene una estructura fija:
Newtonsoft.Json.JsonConvert.SerializeObject(new yourCustomObject)
Al usar esto.
La mejor manera de obtener este resultado
- Tienes que crear una nueva clase que tenga la relación de toda la clase. Luego use el Newtonsoft.Json.JsonConvert.SerializeObject (nueva organización)
Let crea una nueva clase llamada organización. Agregue la relación que desea ver en Json. Luego conviértalo en JSON usando JsonConvert.
O puede usar el siguiente bucle dinámico
//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 = "Department1"}, new {DepartmentId = 2, Name = "Department2"}};
//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);