Sorting Velocity lists on Boolean fields, Part I
Note: There's a contest at the end with a real-world prize!↓
Quick Velocity learner EC asked a seemingly simple question:
How do you sort Velocity objects based on a Boolean field, such that false values come first?
What makes it not-so-simple is that it's actually 3 questions in one!
Realize that something labeled as Boolean in Marketo (in the Field Management or Custom Objects admin sections) may or may not end up as a Boolean field in Velocity.
Booleans on Leads
As I've delved into before, regardless of the data type set in the database, Lead/Person fields in Marketo become String properties of the $lead
object in Velocity:
- Dates and DateTimes are not dates in Velocity, but merely date-like Strings (that's why you need to go through all that pain to convert them).
- Integers are number-like Strings (which can wreak havoc on comparisons if you don't realize it).
- Boolean fields are boolean-ish Strings. They have the possible values
""
(empty String) if the original Boolean was false and numeric String"1"
if it was true.
But the same doesn't hold for Boolean fields on other objects besides the Lead.
Booleans on Oppties and Salesforce COs
On Opportunities and other SFDC Custom Objects, bizarrely, Booleans become a different type of String, which has the possible values "0"
for false and "1"
for true (this is admittedly a more traditional conversion than empty String and "1"
but why, oh why, must it be different?).
Booleans on Marketo COs
On Marketo Custom Objects, Booleans are presented as true Booleans! As in real Java Booleans with the reserved values true and false, the way we dream they'd be everywhere.
Wow, that's confusing!
Uh-huh. As I'm sure you realize, such differences all have to be considered for sorting.
So the 3 questions EC was implicitly asking were:
- How do you sort objects based on a String field that can be empty string
""
or numeric string"1"
, such that""
comes first? - How do you sort objects based on a String field that can be numeric string
"0"
or numeric string"1"
, such that"0"
comes first? - How do you sort objects based on a Boolean field that can be
true
orfalse
, such thatfalse
comes first?
Now, at the code level, the answer to all 3 questions happens to be the same. But this is coincidental because it derives from different Java sorting rules. The fact that there's one answer that covers these 3 cases must not be interpreted to mean any ways of representing true and false will follow the same sorting logic.
At any rate, that answer is:
#set( $sortedList = $sorter.sort($originalList, "fieldName:asc") )
Because ascending (:asc
) is the default order in SortTool, this can be shortened to:
#set( $sortedList = $sorter.sort($originalList, "fieldName") )
So if you have these 3 objects in a list $originalList
:
[{
"Name" : "A",
"IsActive" : false,
"ExternalCreatedDate" : "2017-07-01"
},
{
"Name" : "B",
"IsActive" : true,
"ExternalCreatedDate" : "2017-08-01"
},
{
"Name" : "C",
"IsActive" : false,
"ExternalCreatedDate" : "2017-09-01"
}]
And you do:
#set( $sortedList = $sorter.sort($originalList, "IsActive") )
Then $sortedList
will be:
[{
"Name" : "A",
"IsActive" : false,
"ExternalCreatedDate" : "2017-07-01"
},
{
"Name" : "C",
"IsActive" : false,
"ExternalCreatedDate" : "2017-09-01"
},
{
"Name" : "B",
"IsActive" : true,
"ExternalCreatedDate" : "2017-08-01"
}]
And the same code also works if IsActive
uses either of the 2 boolean-ish String conversions instead of true Boolean.
But again (and I'm going to pound you over the head with this) it's a coincidence. If Marketo happened to use yet another way of String-ifying Booleans, you might need to sort descending ($sorter.sort($originalList, "fieldName:desc")
) or use another sorting method entirely to get the falses to the top.
The challenge
Now, the fun part. Rather than jump right to Part II (where I go deep into the technical details) I'll keep that follow-up post as a draft for a week, until September 18, 2018.
From now 'til Sept. 18, if you're one of the first two people to answer the below challenge correctly — email me your answer, and please only try once per person — I'll send you a $25 Amazon gift card!
The background:
If Marketo used the Strings
"-1"
for false and"+1"
for true then you'd need to use:desc
instead of:asc
. (And there's no standard that says they couldn't String-ify Booleans this way.) Ditto if they'd used the symbols for thumbs-down and thumbs-up,"👎"
and"👍"
(why not, they're also Strings!). And same if they'd used symbols"⊥"
and"⊤"
, which appropriately denote truth and falsity (verum and falsum) in logic.
The question:
Why, in these 3 alternate cases, do you need
:desc
to get the originally false values to come first?
Be precise… no credit for “Because that's what Velocity requires.”☺