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

How to transform complex objects in a list? #298

Open
haufes opened this issue Mar 1, 2024 · 7 comments
Open

How to transform complex objects in a list? #298

haufes opened this issue Mar 1, 2024 · 7 comments

Comments

@haufes
Copy link

haufes commented Mar 1, 2024

I’m trying to perform a transform on elected in an array. I need to update object in an array that has a matching key. If the key matches I need to change the key as well add an Id to the object.

Example payload

{
	"items": [
		{
		    "id": "234234235",
		    "keyTypeA": "One"
		},
		{
	        "keyTypeA": "One"
		},
		{
	        "keyTypeA": "Two"
		},
		{
	        "keyTypeB": "Red"
		}
	]
}

Transformed into

{
	"items": [
		{
		    "id": "987234345",
		    "keyTypeA": "Three"
		},
		{
		    "id": "987234345",
		    "keyTypeA": "Three"
		},
		{
	        "keyTypeA": "Two"
		},
		{
	        "keyTypeB": "Red"
		}
	]
}

Any advice would be appreciated.

@Courela
Copy link
Contributor

Courela commented Mar 2, 2024

This will give you two arrays, you can join them later

{
    "items1": {
        "#loop($.items[?(@.keyTypeA == 'One')])": {
            "id": "some_id",
            "keyTypeA": "some_key"
        }
    },
    "items2": {
        "#loop($.items[?(@.keyTypeA != 'One')])": "#currentvalue()"
    }
}

The only problem is getting elements that don't contain 'keyTypeA' property...

@Courela
Copy link
Contributor

Courela commented Mar 3, 2024

I've notice that a function to negate an argument is missing, something like #not(<bool_value>). I managed to find an ugly workaround for this, though.
I came up with a solution that almost solves the problem, having the same issue as #296, there are some empty objects that are not desired.

Transformer

{
    "items": "#applyover({ 'items1': { '#loop($.items[?/(@.keyTypeA == `One`/)])': { 'id': 'some_id'/, 'keyTypeA': 'some_key' } }/, 'items2': { '#loop($.items[?/(@.keyTypeA != `One`/)])': '#currentvalue()' }/, 'items3': { '#loop($.items)': { '#ifgroup(#ifcondition(#existsandnotempty($.keyTypeA)/,False/,True/,False))': { '#': [ '#copy($)'] } } } }, '#xconcat(#valueof($.items1), #valueof($.items2), #valueof($.items3))')"
}

Output

{
    "items": [{
            "id": "some_id",
            "keyTypeA": "some_key"
        }, {
            "id": "some_id",
            "keyTypeA": "some_key"
        }, {
            "keyTypeA": "Two"
        }, {
		}, {
		}, {
		}, {
            "keyTypeB": "Red"
        }
    ]
}

With #289, transformer would be easier to do and read, without all that escaped charecters

{
    "transform": [{
            "items1": {
                "#loop($.items[?(@.keyTypeA == `One`)])": {
                    "id": "some_id",
                    "keyTypeA": "some_key"
                }
            },
            "items2": {
                "#loop($.items[?(@.keyTypeA != `One`)])": "#currentvalue()"
            },
            "items3": {
                "#loop($.items)": {
                    "#ifgroup(#ifcondition(#exists($.keyTypeA),False,True,False))": {  //ugly workaround for a negate function
                        "#": ["#copy($)"]
                    }
                }
            }
        }, {
            "items": "#xconcat(#valueof($.items1), #valueof($.items2), #valueof($.items3))"
        }
    ]
}

Explanation:

  • 'items1' gets all items with the desired value of 'keyTypeA' and for each one builds another item with the desired properties/values;
  • 'items2' gets all items with 'keyTypeA' value different from what's desired and returns the item;
  • 'items3' gets all items without property 'keyTypeA', returning a copy of the item (the same approach from above can be used, with #currentvalue())

@haufes
Copy link
Author

haufes commented Mar 5, 2024

Hey @Courela Thanks for the sample. Unfortunately I need to have the array without the null elements and ideally the order of the elements would be in the same order, I didn't try with your Courela:feature/multiple_transforms version, is that feature going to be added soon?

@Courela
Copy link
Contributor

Courela commented Mar 5, 2024

I don't know, I'm just a contributor

@haufes
Copy link
Author

haufes commented Mar 7, 2024

I've made some progress with the following transform

{
  "items": {
    "#loop($.items)": {
    "#loop($)": {
       "#eval(#currentproperty())": "#ifcondition(#currentvalueatpath($.keyTypeA),One,Three,#currentvalueatpath(#concat($.,#currentproperty())))"
    }
   }
  }
}

This gets me to

{
  "items": [
    {
      "id": "234234235",
      "keyTypeA": "Three"
    },
    {
      "keyTypeA": "Three"
    },
    {
      "keyTypeA": "Two"
    },
    {
      "keyTypeB": "Red"
    }
  ]
}

Now I just need to add or update the id. I thought that I should be able t
o add more logic in the #loop($.items)" after the #loop($) but it doesn't seam result in anything.

Note: I need to be able to pass any elements of the item without the transform being aware of them,

@Courela
Copy link
Contributor

Courela commented Mar 27, 2024

This works

{
  "items": {
    "#loop($.items)": {
    "#loop($)": {
       "#eval(#currentproperty())": "#ifcondition(#currentproperty(),id,987234345,#ifcondition(#currentvalueatpath($.keyTypeA),One,Three,#currentvalueatpath(#concat($.,#currentproperty()))))"
    }
   }
  }
}

@haufes
Copy link
Author

haufes commented Mar 28, 2024

Hey @Courela, thanks that's closer to what I need, but that isn't quite right.

The logic is if the element of the array has a property of "keyTypeA" with a value of "One".

  1. Change the value to Three".
  2. If the element has a property of "id" change it's value to "987234345"
  3. If the element does not have a property of "id" append a new one with a value of "987234345"

There doesn't seam to be a away to append a property to an element.

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