-1

Convert nested JSON Dictionary<string, JValue> to excel worksheet

The json strings that I deal with have x levels and each time they are different json strings.

Json string:
[{
"nombreId":1016,
"nombre":John,
"proyectos":[
    {"proyectoId":1,"nombre":ProyectoEmpleados},
    {"proyectoId":20,"nombre":ProyectoNominas},
    ],
"nombreId":1056,
"nombre":Sara,
"proyectos":[
    {"proyectoId":22,"nombre":ProyectoContabilidad},
    {"proyectoId":nombre,"nombre":ProyectoNominas},
    ]
}]

I have parsed a nested json string to Dictionary<string, JValue> like this:

public class JsonColeccionCampo
{
    private readonly Dictionary<string, JValue> campos;
    public JsonColeccionCampo(JToken token)
    {
        campos = new Dictionary<string, JValue>();
        ObtenerCampos(token);            
    }       
    
    private void ObtenerCampos(JToken jToken)
    {
        switch (jToken.Type)
        {
            case JTokenType.Object:
                foreach (var child in jToken.Children<JProperty>())
                    ObtenerCampos(child);
                break;
            case JTokenType.Array:
                foreach (var child in jToken.Children())
                   ObtenerCampos(child);
                break;
            case JTokenType.Property:
                ObtenerCampos(((JProperty)jToken).Value);
                break;
            default:
                //forma campos:
                campos.Add(jToken.Path, (JValue)jToken);                 
                break;
        }
    }
    public Dictionary<string, JValue> GetAllCampos() => campos;
}

// the call:

private Dictionary<string, JValue> obtenerCamposApartirdeJson(string parametroJson)
{

    Dictionary<string, JValue> estructuraLista = null;
    if (!string.IsNullOrEmpty(parametroJson))
    {
        var json = JToken.Parse(parametroJson);
        var fieldsCollector = new Comun.JsonColeccionCampo(json);
        estructuraLista = fieldsCollector.GetAllCampos();
    }
    return estructuraLista;
}

// I have a list "estructuraLista" or type Dictionary<string, JValue> like this:

        filas   Count = 11  System.Collections.Generic.Dictionary<string, Newtonsoft.Json.Linq.JValue>
        [0] {[[0].nombreId, 1016]}  System.Collections.Generic.KeyValuePair<string, Newtonsoft.Json.Linq.JValue>
        [1] {[[0].nombre, John]}    
        [2] {[[0].proyecto[0].proyectoId, 1]}   
        [3] {[[0].proyecto[0].Nombre, ProyectoEmpleados]}   
        [4] {[[0].proyecto[1].proyectoId, 20]}  
        [5] {[[0].proyecto[1].Nombre, ProyectoNominas]}
        [6] {[[1].nombreId, 1056]}  
        [7] {[[1].nombre, Sara]}    
        [8] {[[1].proyecto[0].proyectoId, 22]}  
        [9]{[[1].proyecto[0].Nombre, ProyectoContabilidad]} 
        [10]{[[1].proyecto[1].proyectoId, 20]}
        [11]{[[1].proyecto[1].Nombre, ProyectoNominas]} 

I need to treat the list Dictionary<string, JValue> and then pass them to an excel file in this way:

    NombreId    Nombre  ProyectoId  Nombre
    1016        John    1016        ProyectoEmpleados       
                        20          ProyectoNominas
    1056        Sara    22          ProyectoContabilidad
                        20          ProyectoNominas
        

Any idea?

dbc
  • 104,963
  • 20
  • 228
  • 340
ararb78
  • 1,137
  • 5
  • 19
  • 44
  • Probably this would be much easier with Newtonsoft JSON using JsonConvert. Would you share your sample JSON instead. – Cetin Basoz May 09 '21 at 16:29
  • If you want to convert a `JToken` to a `Dictionary` where the key is the path and the value is the primitive value, see [How do I convert a JSON object into a dictionary with Path being the key](https://stackoverflow.com/q/27749114/3744182). You are using `Dictionary` but you will probably want to convert to `JValue.Value` at some point. But, can you [edit] your question to share a [mcve] showing your JSON? It's not clear that flattening to a `Dictionary` is the right way to go about structuring your JSON for output to Excel. – dbc May 09 '21 at 16:45
  • The JSON included in your question seems to be malformed. Upload it to https://jsonlint.com/ and you will get errors such as `Error: Parse error on line 3: Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '[', got 'undefined'`. Seems like a lot of values are not quoted correctly. Might you please share well-formed JSON that demonstrates your problem? – dbc May 09 '21 at 16:53
  • Also, how are you currently outputting to Excel? Are you writing to CSV? `Microsoft.Office.Interop.Excel`? `OleDb`? Something else? There are a bunch of options shown in e.g. [How to write some data to excel file(.xlsx)](https://stackoverflow.com/q/23041021/3744182). – dbc May 09 '21 at 16:56

1 Answers1

0

IMHO, it is better if you use Newtonsoft.Json and Epplus libraries from Nuget for this. ie:

void Main()
{
    var people = JsonConvert.DeserializeObject<Item[]>(json);
    ExcelPackage pck = new ExcelPackage();
    var ws = pck.Workbook.Worksheets.Add("MyWs");
    
    var proyectos = 0;
    for (int i = 0; i < people.Length; i++)
    {
        ws.Cells[$"A{proyectos + 1}"].Value = people[i].NombreId;
        ws.Cells[$"B{proyectos + 1}"].Value = people[i].Nombre;
        ws.Cells[$"C{proyectos + 1}"].LoadFromCollection(people[i].Proyectos,false);
        proyectos += people[i].Proyectos.Length;
    }
    ws.Cells[ws.Dimension.Address].AutoFitColumns();


    var fi = new FileInfo(@"c:\temp\MySample.xlsx");
    if (fi.Exists)
    {
        fi.Delete();
    }
    pck.SaveAs(fi);
}

string json = @"[
{
 ""nombreId"":1016,
 ""nombre"":""John"",
 ""proyectos"":[
     {""proyectoId"":1,""nombre"":""ProyectoEmpleados""},
     {""proyectoId"":20,""nombre"":""ProyectoNominas""} ]
},
{
""nombreId"":1056,
""nombre"":""Sara"",
""proyectos"":[
     {""proyectoId"":22,""nombre"":""ProyectoContabilidad""},
     {""proyectoId"":23,""nombre"":""ProyectoNominas""}
     ]
}]";

public class Item
{
    [JsonProperty("nombreId")]
    public int NombreId { get; set; }

    [JsonProperty("nombre")]
    public string Nombre { get; set; }

    [JsonProperty("proyectos")]
    public Proyecto[] Proyectos { get; set; }
}

public partial class Proyecto
{
    [JsonProperty("proyectoId")]
    public int ProyectoId { get; set; }

    [JsonProperty("nombre")]
    public string Nombre { get; set; }
}
Cetin Basoz
  • 22,495
  • 3
  • 31
  • 39