Saltar al contenido

C# aplanando la estructura json

Por fin después de mucho batallar ya hallamos la contestación de este asunto que ciertos los usuarios de nuestro sitio web tienen. Si deseas aportar algún dato no dejes de compartir tu comentario.

Solución:

JObject jsonObject=JObject.Parse(theJsonString);
IEnumerable jTokens = jsonObject.Descendants().Where(p => p.Count() == 0);
Dictionary results = jTokens.Aggregate(new Dictionary(), (properties, jToken) =>
                    
                        properties.Add(jToken.Path, jToken.ToString());
                        return properties;
                    );

Tenía el mismo requisito de aplanar una estructura json anidada en un objeto de diccionario. Encontré la solución aquí.

Puede usar https://github.com/jsonfx/jsonfx para deserializar json en un objeto dinámico. Luego use ExpandoObject para obtener lo que desea.

public Class1()
        
            string json = @"
                                ""name"": ""test"",
                                ""father"": 
                                     ""name"": ""test2"",
                                     ""age"": 13,
                                     ""dog"": 
                                         ""color"": ""brown""
                                     
                                
                            ";

            var reader = new JsonFx.Json.JsonReader();
            dynamic output = reader.Read(json);
            Dictionary dict = new Dictionary();

            GenerateDictionary((System.Dynamic.ExpandoObject) output, dict, "");
        

        private void GenerateDictionary(System.Dynamic.ExpandoObject output, Dictionary dict, string parent)
        
            foreach (var v in output)
            
                string key = parent + v.Key;
                object o = v.Value;

                if (o.GetType() == typeof(System.Dynamic.ExpandoObject))
                
                    GenerateDictionary((System.Dynamic.ExpandoObject)o, dict, key + ".");
                
                else
                
                    if (!dict.ContainsKey(key))
                    
                        dict.Add(key, o);
                    
                
            
        

A partir de .NET Core 3.0 JsonDocument es una forma (no se necesita Json.NET). Estoy seguro de que esto será más fácil.

using System.Linq;
using System.Text.Json;
(...)


public static Dictionary GetFlat(string json)

    IEnumerable<(string Path, JsonProperty P)> GetLeaves(string path, JsonProperty p)
        => p.Value.ValueKind != JsonValueKind.Object
            ? new[]  (Path: path == null ? p.Name : path + "." + p.Name, p) 
            : p.Value.EnumerateObject() .SelectMany(child => GetLeaves(path == null ? p.Name : path + "." + p.Name, child));

    using (JsonDocument document = JsonDocument.Parse(json)) // Optional JsonDocumentOptions options
        return document.RootElement.EnumerateObject()
            .SelectMany(p => GetLeaves(null, p))
            .ToDictionary(k => k.Path, v => v.P.Value.Clone()); //Clone so that we can use the values outside of using

Una versión más expresiva se muestra a continuación.

Prueba

using System.Linq;
using System.Text.Json;
(...)

var json = @"
    ""name"": ""test"",
    ""father"": 
            ""name"": ""test2"", 
         ""age"": 13,
         ""dog"": 
                ""color"": ""brown""
         
        
    ";

var d = GetFlat(json);
var options2 = new JsonSerializerOptions  WriteIndented = true ;
Console.WriteLine(JsonSerializer.Serialize(d, options2));

Producción


  "name": "test",
  "father.name": "test2",
  "father.age": 13,
  "father.dog.color": "brown"

Versión más expresiva

using System.Linq;
using System.Text.Json;
(...)

static Dictionary GetFlat(string json)
    
        using (JsonDocument document = JsonDocument.Parse(json))
        
            return document.RootElement.EnumerateObject()
                .SelectMany(p => GetLeaves(null, p))
                .ToDictionary(k => k.Path, v => v.P.Value.Clone()); //Clone so that we can use the values outside of using
        
    


    static IEnumerable<(string Path, JsonProperty P)> GetLeaves(string path, JsonProperty p)
    
        path = (path == null) ? p.Name : path + "." + p.Name;
        if (p.Value.ValueKind != JsonValueKind.Object)
            yield return (Path: path, P: p);
        else
            foreach (JsonProperty child in p.Value.EnumerateObject())
                foreach (var leaf in GetLeaves(path, child))
                    yield return leaf;
    

Recuerda que tienes autorización de reseñar si te ayudó.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *