Change all Keys in JSON structure to lowercase
In a mapper, we need to convert all keys of a JSON file at every level to lowercase.
Example:
{"Id":"600b31dadece310027cdf492",
"User":{"Id":"5cbf7330263cd09f9445bd90","displayName":"coyote","impersonatedBy":"ldap:123456"}
}
In this case, we would want to change "Id" & "User" to lowercase, but also the sub-object key elements of User: Id, displayName, and impersonatedBy to lowercase. So, the desired result is:
{"id":"600b31dadece310027cdf492",
"user":{"id":"5cbf7330263cd09f9445bd90","displayname":"coyote","impersonatedby":"ldap:123456"}
}
What is the best JavaScript code (in the Mapper) for this scenario?
Coyote - this is actually a fairly tricky question. Since the SnapLogic expression language doesn't allow for multi-line syntax, the only solution without reverting to a Script snap would be to create an expression that can call itself recursively. This is where expression libraries will come in to help us. I apologize that I don't have a lot of time to completely detail out my answer, but will give you what I can in just a few minutes.
First, the solution. Please find the sample pipeline and expression library file attached here. Just download it, then upload the expr lib file to your project, then import the SLP with the example pipeline. You'll see your requested object as well as an additional array to test nested arrays containing objects. Basically I just wanted to test a more complex example to ensure I had that working correctly.
The call to the expr lib function is very simple:
I'm just putting the results back to the root object in the target path ($).
But let's take a look in the lib expr file itself to see how it's doing this:
lowerCaseKeys : (obj) => // Recursively convert all object keys to lowercase obj .mapValues((val,key) => match typeof val { 'object' => this.lowerCaseKeys (val) , 'array' => val.map(elem => typeof elem == 'object' ? this.lowerCaseKeys(elem) : elem) , _ => val } ) .mapKeys((val,key) => key.toLowerCase())
I'm first calling the Object.mapValues() method to check for any sub-elements that are objects or array of objects - in either case, I'm going to recursively call the lowerCaseKeys() function to do that next lower level of the nested object, leaving all the current values as-is.
After we're done with the mapValues() call, then I can do the rest of the keys at the root level using the Object.mapKeys() method.
Other operations used:
- match control operator
- ternary conditional operator (see Understanding Expressions document)
I also included an upperCaseKeys() function in the expr file for completeness. There are other functions in the expr file that would take much longer to explain, but are just as useful as what I've explained here.
Hope this helps!