Site icon FileMakerHacks

Ordering Elements within JSON Objects

Introduction

If you’ve generated JSON objects via FileMaker, you’re likely aware of the disparity between the order in which you specify the elements, and the order in which they subsequently appear (i.e., alphabetized by key name). As I wrote two years ago (in Thinking About JSON, Part 2)…

Both JSONSetElement and JSONFormatElements will automatically alphabetize key/value pairs within JSON objects. This can be disconcerting if you aren’t expecting it, but eventually you work through the stages of grief and come to accept that it’s just the way things are. The JSON Data Interchange Standard definition at json.org specifies that “An object is an unordered [emphasis mine] set of name/value pairs”, whereas an array is an “ordered collection of values”. In other words, by definition the order of the key/value pairs within JSON objects simply does not, and should not, matter.

Well… okay… you know that, and I know that, and FileMaker knows that, as do the JSON Jedi… but what if you are demonstrating a proof of concept to a client, and to avoid cognitive dissonance and unnecessary explanation you’d like to “doctor the evidence” (so to speak) and order the elements meaningfully?

For example, you’d like them to see this…

…as opposed to what they would see if you took a standard approach to generating the JSON object:

Today we’re going to look at a couple hacks to make the first example viable, and the basic idea is the same in both cases:

Note: the standard disclaimer applies that there may be (actually there are) edge cases where this could fail. But 99.99% of the time these approaches will work just fine. As with all techniques on this site proceed with caution and use at your own risk.

Hack #1: Stealth Array

Substitute ( 

JSONFormatElements ( 
   JSONSetElement ( "[]" ; 
      [ 0 ; JSONSetElement ( "{}" ; "Table of Contents" ; "This comes first" ; JSONString ) ; JSONObject ] ;
      [ 1 ; JSONSetElement ( "{}" ; "Foreword" ; "This comes second" ; JSONString ) ; JSONObject ] ;
      [ 2 ; JSONSetElement ( "{}" ; "Introduction" ; "This comes third" ; JSONString ) ; JSONObject ] ;
      [ 3 ; JSONSetElement ( "{}" ; "Body" ; "This comes fourth" ; JSONString ) ; JSONObject ] ; 
      [ 4 ; JSONSetElement ( "{}" ; "Appendix" ; "This comes fifth" ; JSONString ) ; JSONObject ] ; 
      [ 5 ; JSONSetElement ( "{}" ; "Index" ; "This comes last" ; JSONString ) ; JSONObject ] 
   )
) ; 

[ "[¶" & Char ( 9 ) & "{¶" & Char ( 9 ) & Char ( 9 ) ; "{¶" & Char ( 9 ) ] ; 
[ "¶" & Char ( 9 ) & "},¶" & Char ( 9 ) & "{¶" & Char ( 9 ) & Char ( 9 ) ; ",¶" & Char ( 9 ) ] ; 
[ "¶" & Char ( 9 ) & "}¶]" ; "¶}" ]  

)

8 May 2020 — actually this can be simplified (as per Paul Jansen’s comment at the end of the article).

Substitute (

JSONSetElement ( "[]" ;
[ "[0].Table of Contents" ; "This comes first" ; JSONString] ;
[ "[1].Foreword" ; "This comes second" ; JSONString ] ;
[ "[2].Introduction" ; "This comes third" ; JSONString ] ;
[ "[3].Body" ; "This comes fourth" ; JSONString ] ;
[ "[4].Appendix" ; "This comes fifth" ; JSONString ] ;
[ "[5].Index" ; "This comes last" ; JSONString ]
)

; [ "},{" ; ",¶" & char(9) ]
; [ "[{" ; "{¶" & char(9) ]
; [ "}]" ; "¶}" ]

)

Explanation:

Hack #2: Numeric Prependectomy

This idea is courtesy of Paul Jansen and uses the While function so requires FM 18 or later.

The result we’d like to display:

How we get there:

While ( [ 
~json = JSONFormatElements ( JSONSetElement ( "{}" ; 
[ "!000!first" ; "blah" ; JSONString ] ; 
[ "!001!second" ; "blah" ; JSONString ] ; 
[ "!002!third" ; "blah" ; JSONString ] ; 
[ "!003!fourth" ; "blah" ; JSONString ] ; 
[ "!004!fifth" ; "blah" ; JSONString ] ; 
[ "!005!sixth" ; "blah" ; JSONString ] ; 
[ "!006!seventh" ; "blah" ; JSONString ] ; 
[ "!007!eighth" ; "blah" ; JSONString ] ; 
[ "!008!ninth" ; "blah" ; JSONString ] ; 
[ "!009!tenth" ; "blah" ; JSONString ] ; 
[ "!010!eleventh" ; "blah" ; JSONString ] ; 
[ "!011!twelth" ; "blah" ; JSONString ] ; 
[ "!012!thirteenth" ; "blah" ; JSONString ] 
) ) ; 
~count = ValueCount ( JSONListKeys ( ~json ; "" ) ) ; 
~i = 0 ] ; 
~i < ~count ; 
[ ~json = Substitute ( ~json ; "!" & Right ( "00" & ~i ; 3 ) & "!" ; "" ) ; 
  ~i = ~i + 1 ] ; 
~json
)

Explanation:

Here’s what can happen if you don’t zero pad (though of course you’ll be fine if there are less than 11 elements in your object):

But Is It Still JSON?

Yes, the result of either of these hacks is 100% valid JSON as far as FM is concerned, e.g.,

…and…

…which is to say that if you chose to generate a JSON object via either of these techniques, FileMaker will recognize the object as if the hack had never been applied in the first place.

Exit mobile version