Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need help with transforming by adding root fields to child array elements #292

Open
allensutton-lumen opened this issue Apr 20, 2023 · 1 comment

Comments

@allensutton-lumen
Copy link

allensutton-lumen commented Apr 20, 2023

Hello,

I have a JSON response from an API call, like this (edited for brevity and obfuscation purposes):

{
    "thing_name": "whatever",
    "thing_uuid": "lkjsadhlkjsa",
    "thing_id": 333333333,
    "child_stuff": [
        {
            "name": "child thing 1",
            "group": "widget flippers",
            "sequence": 0,
            "is_included": true,
            "dependent_on": "widget manufacturers",
            "modifier": 0
        },
        {
            "name": "child thing 2",
            "group": "underwater basket weavers",
            "sequence": 0,
            "is_included": false,
            "dependent_on": "water purification team",
            "modifier": 0
        }
    ]
}

Due to some limitations with the application we're using, I need to sort of flatten this JSON (this is a third-party off the shelf application that only accepts a certain JSON format, but luckily the vendor implemented a JSLT solution to do so), so that it looks like this:

[ 
    { 
        "a" : b, 
        "c" : d 
    }, 
    {
       "w" : x,
        "y" : z
    } 
]

So, using the example from earlier, the expected output would be this:

[
        {
            "thing_name": "whatever",
            "thing_uuid": "lkjsadhlkjsa",
            "thing_id": 333333333,
            "name": "child thing 1",
            "group": "widget flippers",
            "sequence": 0,
            "is_included": true,
            "dependent_on": "widget manufacturers",
            "modifier": 0
        },
        {
            "thing_name": "whatever",
            "thing_uuid": "lkjsadhlkjsa",
            "thing_id": 333333333,
            "name": "child thing 2",
            "group": "underwater basket weavers",
            "sequence": 0,
            "is_included": false,
            "dependent_on": "water purification team",
            "modifier": 0
        }
]

I found a solution that works, but it's a bit clunky:

let thing_name = (.thing_name)
let thing_uuid = (.thing_uuid)
let thing_id = (.thing_id)

[ 
   for (.child_stuff) {
            "thing_name": $thing_name,
            "thing_uuid": $thing_uuid,
            "thing_id": $thing_id,
            "name": .name,
            "group": .group,
            "sequence": .sequence,
            "is_included": .is_included,
            "dependent_on": .dependent_on,
            "modifier": .modifier
       }
 ]

Is there a way to do this more programmatically without having to statically define fields? Ideally I'd be able to use a nested for loop to first loop through the "child_stuff" array and then for each array item, loop through the three root fields and insert those into each child array item. That way if the fields change, I don't have to keep updating them and it "just works". Something like this:

let rootObj = (.)
[
    for(.child_stuff)
    {
        .key : .value,
        for($rootObj)
        if (not(is-array(.key)))
        .key : .value
    }
]

I did find a StackOverflow question that seemed to indicate that you can't pull parent values into a child item and the parent items need to be defined with let statements, which is fine for my purposes. I was trying to do something like this but I can't get the syntax right:

let baseObj = {
    "thing_name" : (.thing_name),
    "thing_uuid" : (.thing_uuid),
    "thing_id" : (.thing_id)
}

[
    for (.child_stuff) 
        { 
            .key : .value, 
            [
                 for ($baseObj) 
                     .key : .value
            ]
        }
]

I tried looking in the documentation, but I don't see anything that specifically mentions this, and searching forums doesn't seem to have a generic enough example for me to understand. Any help would be greatly appreciated.

@jacekszymanski
Copy link

Perhaps this one:

let root_stuff = [ for (.) . if (not(is-array(.value)) and not(is-object(.value))) ]

[
  for (.child_stuff) {
    for ([array(.), $root_stuff] | flatten(.)) .key : .value
  }
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants