Forum Discussion
Hi @ForbinCSD,
The main difference between doc.get("something")
and doc["something"]
is that with the .get()
method if the field is not found in the input data it returns null
, if you are using it without it, it will return an empty object on the output.
var value = doc["readFromInput"];
If readFromInput
does not exist in the input data this variable will simply return undefined
.
If you are using the .get()
method in that case this will return null
.
Example:
var valueWithoutGet = doc["readFromInput"];
var valueWithGet = doc.get("readFromInput");
var output = new LinkedHashMap();
output.put("valueWithoutGet", valueWithoutGet);
output.put("valueWithGet", valueWithGet);
this.output.write(output);
You will simply get the following output:
In both cases there is an output.
If you want to control whether to output that data you can write the logic in the script:
if (valueWithGet != null) {
output.put("value", valueWithGet);
}
Now for the other questions:
- If the
Things
property is sometimes an array and sometimes a scalar, would the lack of.toArray()
cause the script to fail?
- If you have a string value you can obviously traverse it because JavaScript allows it. If you have anything other than a string, you have to convert that to an array. You can use
Arrays.asList(doc["scalar"])
to convert the scalar into an array.
Example input data:
[
{
"scalar": "test string"
}
]
Script:
var doc = this.input.next();
var getValue = doc["scalar"];
var output = new LinkedHashMap();
for (var i = 0; i < getValue.length; i++) {
output.put("Char at " + i, getValue[i]);
}
this.output.write(output);
Example to check if input is array or not and if it is not an array convert it to array:
Note: you have to import the ArrayList and Arrays class in this case.
importClass(java.util.ArrayList);
importClass(java.util.Arrays);
var doc = this.input.next();
var output = new LinkedHashMap();
if (doc["scalar"] instanceof ArrayList) {
output.put("scalar", doc["scalar"])
} else {
output.put("scalar", Arrays.asList(doc["scalar"]));
}
this.output.write(output);
By using the same sample, the “scalar” field is converted into an array.
- If
Things
is sometimes completely absent, do either of the options shown offer any protection? (I’m guessing not , and that you’d need to checktypeof
for'undefined'
.)
- Yes, you have to check and make the logic if some of those values are completely absent.
- Does the
.get()
provide any additional safety (or do anything else beyond what doc[“Something”] does)?
- The methog
.get()
returns null on the output if the input data is not present. This is basically the same as Null-safe access on the Mapper snap.
- Let’s assume the arrays shown above are always arrays. Could someone just as easily (and more clearly) have written the following?
- Yes if they are always arrays and exist in the input data.
- ForbinCSD4 years agoContributor
Wow. Thank you very much for a very complete answer; this was a real education!
My takeaway from this (besides now knowing the details of how these aspects of JavaScript work) is that our offshore developers were generally on the right track and meant well, but failed to execute their intentions.
Which means, if the doc is always intact with all of its expected properties and they’re of the expected (and invariant) types, my code above is just fine (and much easier to read and maintain).
And if the docs vary greatly in their content, then either there’s a deficiency earlier in the pipelines that needs fixing, or else the code needs to protect itself like the following (based on your training I received above)…
execute: function() { this.log.info("Executing Transform Script"); while ( this.input.hasNext() ) { var doc = this.input.next(); var theWhatever = doc.get("Whatever"); if ( theWhatever ) { for ( var i = 0; i < theWhatever.length; ++i ) { var theThings = theWhatever[i].Things.toArray(); if ( theThings ) { for ( var j = 0; j < theThings.length; ++j ) { var foo = theThings[j].something; // do some work } ...
[ The
.toArray()
above being used in lieu ofArrays.asList()
– which I can get away with only because the code doesn’t emit that array in the output. Otherwise I’d be usingjava.util.ArrayList
andjava.util.Arrays
as you mentioned. ]Thanks again for your super-helpful post!
–JohnB, aka “Forbin”