cancel
Showing results for 
Search instead for 
Did you mean: 

Change all Keys in JSON structure to lowercase

Coyote
New Contributor

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?

3 REPLIES 3

koryknick
Employee
Employee

@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: 

koryknick_0-1722361029863.png

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:

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!

This is fantastic, and I like that it is in a lib call so all the mess is hidden (like a function).  I will try this out and let you know.  I really like the simplicity -- even though my understanding of JS is limited for now, I can see the genius.

Another question:  So Arizona State University is new to Snaplogic and so is Javascript.  What is the best resource you know for a formal class (in Javascript) and a self teach program?  I am going to ask for funds for our team if necessary.  

koryknick
Employee
Employee

@Coyote - You can start with the documentation I referenced, and the Array and Object function documentation in particular.  There are also several self-paced courses on the SnapLogic Academy that you might find useful.