Search code examples
c#jsonjson.net

Modifying JSON Hierarchy to move a key down and convert it into a K/V pair C#


Essentially I need to have this:

    "/xxx/dynamicFileName1": {
    "lines": {
        "total": 8,
        "covered": 4,
        "skipped": 0,
        "pct": 50
    },
    "functions": {
        "total": 1,
        "covered": 0,
        "skipped": 0,
        "pct": 0
    },
    "statements": {
        "total": 8,
        "covered": 4,
        "skipped": 0,
        "pct": 50
    },
    "branches": {
        "total": 2,
        "covered": 0,
        "skipped": 0,
        "pct": 0
    }
},
"/xxx/dynamicFileName2": {
    "lines": {
        "total": 13,
        "covered": 4,
        "skipped": 0,
        "pct": 30.77
    },
    "functions": {
        "total": 1,
        "covered": 0,
        "skipped": 0,
        "pct": 0
    },
    "statements": {
        "total": 13,
        "covered": 4,
        "skipped": 0,
        "pct": 30.77
    },
    "branches": {
        "total": 12,
        "covered": 0,
        "skipped": 0,
        "pct": 0
    }
}

Turn into this: (The dynamic file name key is moved down and used as the value in a key value pair)

{
"results": [{
        "Name": "/xxx/dynamicFileName1",
        "lines": {
            "total": 3321,
            "covered": 853,
            "skipped": 0,
            "pct": 25.69
        },
        "statements": {
            "total": 3327,
            "covered": 853,
            "skipped": 0,
            "pct": 25.64
        },
        "functions": {
            "total": 724,
            "covered": 36,
            "skipped": 0,
            "pct": 4.97
        },
        "branches": {
            "total": 1984,
            "covered": 42,
            "skipped": 0,
            "pct": 2.12
        }
    },
    {
        "Name": "/xxx/dynamicFileName2",
        "lines": {
            "total": 3321,
            "covered": 853,
            "skipped": 0,
            "pct": 25.69
        },
        "statements": {
            "total": 3327,
            "covered": 853,
            "skipped": 0,
            "pct": 25.64
        },
        "functions": {
            "total": 724,
            "covered": 36,
            "skipped": 0,
            "pct": 4.97
        },
        "branches": {
            "total": 1984,
            "covered": 42,
            "skipped": 0,
            "pct": 2.12
        }
    }
]}

I'm trying to deserialize the above JSON into classes. Wondering if anyone has dealt with a problem like this before? I've been reading the NewtonSoft docs and I haven't been able to piece anything together. Any help would be appreciated greatly.


Solution

  • The class structure that corresponds to the second JSON is the following:

    public class RootObject
    {
        public List<Result> Results { get; set; }
    }
    
    public class Result
    {
        public string Name { get; set; }
        public Statistics Lines { get; set; }
        public Statistics Statements { get; set; }
        public Statistics Functions { get; set; }
        public Statistics Branches { get; set; }
    }
    
    public class Statistics
    {
        public int Total { get; set; }
        public int Covered { get; set; }
        public int Skipped { get; set; }
        public float Pct { get; set; }
    }
    

    Here is the code you would need to deserialize the first JSON to this class structure. It loads the JSON into a JObject, moves each of the dynamic keys into a Name property on its respective child object, collects the child objects into a list, and finally places the list into a new RootObject instance.

    var root = new RootObject
    {
        Results = JObject.Parse(json)
            .Properties()
            .Select(jp =>
            {
                JObject item = (JObject)jp.Value;
                item.AddFirst(new JProperty("Name", jp.Name));
                return item.ToObject<Result>();
            })
            .ToList()
    };
    

    Here is a working demo: https://dotnetfiddle.net/30xova