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

Transformation Issue - Dynamic JSON #309

Open
NJ2929 opened this issue Sep 16, 2024 · 7 comments
Open

Transformation Issue - Dynamic JSON #309

NJ2929 opened this issue Sep 16, 2024 · 7 comments

Comments

@NJ2929
Copy link

NJ2929 commented Sep 16, 2024

Hi team, I really need your help here as this will be live in 2 days.

I'm not able to achieve the nested loop feature and the code keeps failing, I'm fairly new to JUST.net, really looking for your help here.

My input JSON:

`{
	"entityDataStore": {
		"entityData": {
			"entityParent": {
				"NODE1": "dummy value",
				"NODE2": "dummy value",
				"NODE3": "dummy value",
				"NODE4": "dummy value",
				"entityParent-entityChild": [   
					{
						"Id1": "dummy value",
						"name": "dummy value",
						"entity": "dummy value",
						"ParentName": "dummy value" 
						 
					},
					{
						"Id1": "dummy value",
						"name": "dummy value",
						"entity": "dummy value",
						"ParentName": "dummy value" 
					}
				]
			}
		}
	}
}`

output, what I'm trying to achieve, is as the "entityParent-entityChild" has array of OBJECTS, so its dynamic in nature, I'm looking to recreate it as below:

Output JSON:


`{
	"newChanges": [
		{
			"dataMember": "entityParent-entityChild",
			"rows": [
				{
					"state": "New",
					"rowid": "1",
					"fields": [
						{
							"columnName": "name",
							"originalValue": null,
							"currentValue": "dummy value"
						},
						{
							"columnName": "entity",
							"originalValue": null,
							"currentValue": "dummy value"
						}
					]
				},
				{
					"state": "New",
					"rowid": "2",
					"fields": [
						{
							"columnName": "name",
							"originalValue": null,
							"currentValue": "dummy value"
						},
						{
							"columnName": "entity",
							"originalValue": null,
							"currentValue": "dummy value"
						}
					]
				}
			]
		}
	]
}`

My Transformation: (Currently I have written to fetch a column only to see, if it will work or not, sadly i get an error 'Unexpected character encountered while parsing path'


`{
  "entityDataStore": {
    "#loop($.entityDataStore.entityData.entityParent, rows)": {

      "fields": {
        "#loop($.entityParent-entityChild)": {
          "entity": "#currentvalueatpath($.entity)"
        }
      }
    }
  }
}
`

My C# code:

`                    
 string input = jsonResponse;
string createTransformation= File.ReadAllText("<file.JSON>");
 string transformedString = JsonTransformer.Transform(createTransformation, input);
`
@Courela
Copy link
Contributor

Courela commented Sep 16, 2024

The first loop

"#loop($.entityDataStore.entityData.entityParent, rows)": {

it's a loop over an object, so it will output an object as well. Since you are defining "fields" property on every iteration, it will try to add property "fields" to output object more than once, which is not allowed.

Without thinking too hard, I came up with this
Transformer:

{
    "newChanges": {
        "dataMember": "entityParent-entityChild",
        "fields": {
            "entityDataStore": {
                "#loop($.entityDataStore.entityData.entityParent.entityParent-entityChild, rows)": {
                    "#loop($)": {
                        "#eval(#xconcat(val,#currentindex()))": {
                            "columnName": "#currentproperty()",
                            "originalValue": null,
                            "currentValue": "#currentvalueatpath(#xconcat($.,#currentproperty()))"
                        }
                    }
                }
            }
        }
    }
}

Output:

{
    "newChanges": {
        "dataMember": "entityParent-entityChild",
        "fields": {
            "entityDataStore": [{
                    "val0": {
                        "columnName": "Id1",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val1": {
                        "columnName": "name",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val2": {
                        "columnName": "entity",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val3": {
                        "columnName": "ParentName",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    }
                }, {
                    "val0": {
                        "columnName": "Id1",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val1": {
                        "columnName": "name",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val2": {
                        "columnName": "entity",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val3": {
                        "columnName": "ParentName",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    }
                }
            ]
        }
    }
}

That's not exactly what you want, but it's a start.

Btw, this uses the latest version published
https://www.nuget.org/packages/JUST.net/4.4.1

@NJ2929
Copy link
Author

NJ2929 commented Sep 17, 2024

The first loop

"#loop($.entityDataStore.entityData.entityParent, rows)": {

it's a loop over an object, so it will output an object as well. Since you are defining "fields" property on every iteration, it will try to add property "fields" to output object more than once, which is not allowed.

Without thinking too hard, I came up with this Transformer:

{
    "newChanges": {
        "dataMember": "entityParent-entityChild",
        "fields": {
            "entityDataStore": {
                "#loop($.entityDataStore.entityData.entityParent.entityParent-entityChild, rows)": {
                    "#loop($)": {
                        "#eval(#xconcat(val,#currentindex()))": {
                            "columnName": "#currentproperty()",
                            "originalValue": null,
                            "currentValue": "#currentvalueatpath(#xconcat($.,#currentproperty()))"
                        }
                    }
                }
            }
        }
    }
}

Output:

{
    "newChanges": {
        "dataMember": "entityParent-entityChild",
        "fields": {
            "entityDataStore": [{
                    "val0": {
                        "columnName": "Id1",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val1": {
                        "columnName": "name",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val2": {
                        "columnName": "entity",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val3": {
                        "columnName": "ParentName",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    }
                }, {
                    "val0": {
                        "columnName": "Id1",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val1": {
                        "columnName": "name",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val2": {
                        "columnName": "entity",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val3": {
                        "columnName": "ParentName",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    }
                }
            ]
        }
    }
}

That's not exactly what you want, but it's a start.

Btw, this uses the latest version published https://www.nuget.org/packages/JUST.net/4.4.1

Thanks a lot, I solved this by looping over the child array also your solution is valid as well, I will check it out as well, Now, I have another issue for which I'm going to comment here. it is not working when I do not have an array for a particular property.
Thanks for ton for the quick prompt.

@NJ2929
Copy link
Author

NJ2929 commented Sep 17, 2024

The first loop

"#loop($.entityDataStore.entityData.entityParent, rows)": {

it's a loop over an object, so it will output an object as well. Since you are defining "fields" property on every iteration, it will try to add property "fields" to output object more than once, which is not allowed.

Without thinking too hard, I came up with this Transformer:

{
    "newChanges": {
        "dataMember": "entityParent-entityChild",
        "fields": {
            "entityDataStore": {
                "#loop($.entityDataStore.entityData.entityParent.entityParent-entityChild, rows)": {
                    "#loop($)": {
                        "#eval(#xconcat(val,#currentindex()))": {
                            "columnName": "#currentproperty()",
                            "originalValue": null,
                            "currentValue": "#currentvalueatpath(#xconcat($.,#currentproperty()))"
                        }
                    }
                }
            }
        }
    }
}

Output:

{
    "newChanges": {
        "dataMember": "entityParent-entityChild",
        "fields": {
            "entityDataStore": [{
                    "val0": {
                        "columnName": "Id1",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val1": {
                        "columnName": "name",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val2": {
                        "columnName": "entity",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val3": {
                        "columnName": "ParentName",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    }
                }, {
                    "val0": {
                        "columnName": "Id1",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val1": {
                        "columnName": "name",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val2": {
                        "columnName": "entity",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    },
                    "val3": {
                        "columnName": "ParentName",
                        "originalValue": null,
                        "currentValue": "dummy value"
                    }
                }
            ]
        }
    }
}

That's not exactly what you want, but it's a start.

Btw, this uses the latest version published https://www.nuget.org/packages/JUST.net/4.4.1

Hi Courela,

What I observed is, sometimes the parent node isn't array of objects, so the loop is failing, in that case what would be the ideal approach to achieve this ?
Ex: 'EntityParent-entityChild' property isn't always an array of object. sometimes it is like below, just one object and not array.
so I have to dynamically check if the 'EntityParent-entityChild' is an array then use the LOOP JSON structure else just fetch the value from the nodes (from #valueOf) function.

How can this be done in JUST ? Could you please help me here

{
	"entityDataStore": {
		"entityData": {
			"entityParent": {
				"NODE1": "dummy value",
				"NODE2": "dummy value",
				"NODE3": "dummy value",
				"NODE4": "dummy value",
				"entityParent-entityChild":  
					{
						"Id1": "dummy value",
						"name": "dummy value",
						"entity": "dummy value",
						"ParentName": "dummy value" 
						 
					}
			}
		}
	}
}

@Courela
Copy link
Contributor

Courela commented Sep 17, 2024

You can try #isarray Type Check

@NJ2929
Copy link
Author

NJ2929 commented Sep 17, 2024

You can try #isarray Type Check

Hi, I tried this but it doesn't work, in the sense, the way I want it to be, here is what I'm trying to achieve:

when the property is an array-> Create a transformation which has #loop function in it.
when the property is not an array -> Create a simple transformation where the values are fetched with #valueof function of this library.

my transformation file:
"isArrayDoc" : "#isarray(#valueof($.entity1.entity2))" -> this will give me either true or false but on the basis of TRUE or FALSE I need to create my JSON.

so what I tried, is to include, #ifcondition.

but I think, this wont work In this library. let me know your thought.

"isArrayDoc" : "#ifcondition(#isarray(#valueof($.entity1.entity2)),true, <**use the json transform 1**> , <**use the json transform 2**>"

json transform 1:

{
    "newChanges": {
        "dataMember": "entityParent-entityChild",
        "fields": {
            "entityDataStore": {
                "#loop($.entityDataStore.entityData.entityParent.entityParent-entityChild, rows)": {
                    "#loop($)": {
                        "#eval(#xconcat(val,#currentindex()))": {
                            "columnName": "#currentproperty()",
                            "originalValue": null,
                            "currentValue": "#currentvalueatpath(#xconcat($.,#currentproperty()))"
                        }
                    }
                }
            }
        }
    }
}

json transformer 2:

{
  "entityDataStore": {
          "entity": "#valueOf($.entity)"
        }
}

Now, I don't think, I can replace the whole string for (json transformer 1 and 2) in the IF condition, I tried doing it but it wont allow as there are double inverted commas which I can't escape in this library.

Please let me know your suggestions.

@Courela
Copy link
Contributor

Courela commented Sep 17, 2024

This would probably be a situation to use this
#289
but was not merged yet.

#ifgroup function would be better in this case, I think, but it has the problem of creating empty objects if the condition is not met.

@NJ2929
Copy link
Author

NJ2929 commented Sep 17, 2024

This would probably be a situation to use this #289 but was not merged yet.

#ifgroup function would be better in this case, I think, but it has the problem of creating empty objects if the condition is not met.

Ah I see, I'm not looking to create empty objects, I will check, 289, which you mentioned, though for now, I was able to do it via simple if and else statement of the c# language.

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