Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flattening json structure with arrays to multiple flat objects without arrays

I'm not sure whether did I describe the problem in subject 100% correctly, but I believe that the examples will do the trick.

I have JSON structure like below (note: there is small chance that this might change, so i need to lean forward to generic solution)

One invoice with multiple line items:

{
    "contactName": "Company",
    "lineItems": [
     {
        "quantity": 7.0,
        "description": "Beer No* 45.5 DIN KEG"
     },
     {
        "quantity": 2.0,
        "description": "Beer Old 49.5 DIN KEG"
     }
     ],
    "invoiceNumber": "C6188372"
}

And this is the wanted result data structure (multiple invoices with duplicated data and different line item info):

[{
    "contactName": "Company",
    "quantity": 7.0,
    "description": "Beer No* 45.5 DIN KEG"
    "invoiceNumber": "C6188372"
},{
    "contactName": "Company",
    "quantity": 2.0,
    "description": "Beer Old 49.5 DIN KEG"
    "invoiceNumber": "C6188372"
}]

So each "line item" from "invoice" should "result" in new invoice with duplicated other elements.

Small variations around result data structure are accepted, i can adjust my code around it. I've been spinning around using several similar questions such as:

  • C# flattening json structure
  • Flatten an array of objects that may contain arrays
  • How can I flatten a collection of objects (which in turn contain collections)?
  • Generically Flatten Json using c# (etc). i believe that this is the closest solution? but unsure if there is some better approach

For more background, i need this for CSV export. So result set should be two rows in generated CSV.

Any hints/tips are much appreciated. Thanks.

like image 772
Ivan Kalafatić Avatar asked Jan 27 '23 12:01

Ivan Kalafatić


1 Answers

You could do it with a function like this:

//Pass in the name of the array property you want to flatten
public string FlattenJson(string input, string arrayProperty)
{
    //Convert it to a JObject
    var unflattened = JsonConvert.DeserializeObject<JObject>(input);

    //Return a new array of items made up of the inner properties
    //of the array and the outer properties
    var flattened = ((JArray)unflattened[arrayProperty])
        .Select(item => new JObject(
            unflattened.Properties().Where(p => p.Name != arrayProperty), 
            ((JObject)item).Properties()));

    //Convert it back to Json
    return JsonConvert.SerializeObject(flattened);
}

And call it like this:

var flattenedJson = FlattenJson(inputJson, "lineItems");
like image 137
DavidG Avatar answered Jan 31 '23 18:01

DavidG