├── JSON.fmp12 ├── README.markdown ├── ChangelogApp.markdown ├── ChangelogModule.markdown └── fmdiff ├── standard.css └── JSON 1.0.2.html /JSON.fmp12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dansmith65/FileMaker-JSON/HEAD/JSON.fmp12 -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | ## Overview ## 2 | 3 | Provides native support for JSON in FileMaker. It will parse JSON encoded text into a format that can easily be read via custom functions. It will also convert text encoded by custom functions into JSON. 4 | 5 | ## Where to Start ## 6 | 7 | Read the `Modules -> JSON -> JSON: READ ME` script. Go to http://www.modularfilemaker.org/ to learn more about modules. -------------------------------------------------------------------------------- /ChangelogApp.markdown: -------------------------------------------------------------------------------- 1 | ### 1.0.4 ### 2 | 3 | - add unit tests for FM-JSON: 4 | - value is json list 5 | - value is json object 6 | 7 | 8 | ### 1.0.3 ### 9 | 10 | - add unit tests for JSON-FM and FM-JSON: 11 | - GitHub Issue #7: Printer quotes ruin your day: in array 12 | - GitHub Issue #7: Printer quotes ruin your day: in object 13 | 14 | 15 | ### 1.0.2 ### 16 | 17 | - add unit tests for FM-JSON: 18 | - unicode control characters w/ backslash escape 19 | - unicode 0 20 | - unicode control characters w/out backslash escape 21 | 22 | - add Speed Test scripts: 23 | - Speed Test: Template 24 | - Speed Test: Substitute vs Filter 25 | - Speed Test: Text vs Char function 26 | 27 | 28 | ### 1.0.1 ### 29 | 30 | - unit tests for FM-JSON: 31 | - "text miss-interpreted as a date" unit test now produces expected result 32 | - add unit tests for "quoted number treated as list" bug 33 | - add misc. unit tests 34 | - add unit tests with large chunks of data to better represent real-world data 35 | 36 | - update custom functions to current #Parameters module version 1.1.3: 37 | - # 38 | - #List 39 | 40 | 41 | # 1.0.0 # 42 | 43 | - the first release of this file did not include a separate version script for the application. This version script was created with JSON: Version 1.0.1. 44 | - updated custom functions: 45 | # 46 | #GetNameList 47 | #List 48 | - add unit tests for JSON-FM: 49 | - Object with returns 50 | - Array with returns 51 | - unit tests for FM-JSON: 52 | - modify: Escape characters pt 2: returns/line endings 53 | - add: Escape characters pt 4: returns/line endings in object 54 | - scripts 55 | - added 56 | - JSON-FM: Go To 57 | - FM-JSON: Go To 58 | - deleted 59 | - Toggle section 60 | - modified 61 | - FM-JSON: Parse All Found 62 | - FM-JSON: Parse letNotation text { skipRefresh } 63 | - FM-JSON: Parse letNotation expression { skipRefresh } 64 | - update navigation button in header -------------------------------------------------------------------------------- /ChangelogModule.markdown: -------------------------------------------------------------------------------- 1 | ### 1.0.6 ### 2 | 3 | release date: 2017-DEC-01 4 | 5 | When converting FM to JSON and a value is already a JSON object or array, don't convert it to a string. 6 | 7 | - modify scripts: 8 | - ~JSON-FM String 9 | 10 | 11 | ### 1.0.5 ### 12 | 13 | release date: 2016-MAY-05 14 | 15 | - modify scripts: 16 | - FM-JSON ( letNotation ) 17 | - ~JSON-FM Value 18 | - ~JSON-FM String 19 | - ~FM-JSON { value } 20 | 21 | 22 | ### 1.0.4 ### 23 | 24 | release date: 2015-MAR-30 25 | 26 | - modify scripts: 27 | - ~FM-JSON { value } 28 | - fix bug: time or timestamp with milliseconds would use the right two digits as the seconds and would not display milliseconds 29 | - fix bug: (GitHub Issue #6) return delimited list of field names from the current layout were detected as an array 30 | - now requires an array to end in a trailing return (which is the format produced by the #List function) 31 | - modified the "manually generated array" unit tests to reflect this change 32 | 33 | 34 | ### 1.0.3 ### 35 | 36 | - modify scripts: 37 | - ~FM-JSON { string } 38 | - fix bug: encode unicode control characters 39 | 40 | 41 | ### 1.0.2 ### 42 | 43 | - modify scripts: 44 | - ~FM-JSON { value } 45 | - update test that differentiates an array from a string 46 | - previously, a quoted number was interpreted as an array 47 | - ~JSON-FM Object 48 | - update # ( name ; value ) function used in encode object section to version date 2014-06-06 49 | - ~JSON-FM Array 50 | - update #List ( value ) function used in encode value section to version date 2014-06-06 51 | - JSON: READ ME 52 | - add "UPGRADE PROCESS" section 53 | 54 | 55 | ### 1.0.1 ### 56 | 57 | - fix Issue #1 and #2 from GitHub 58 | - modify scripts: 59 | - JSON: Changelog: Detailed 60 | - deleted, will store list of all changes in the version script instead 61 | - ~JSON-FM Object 62 | - update # ( name ; value ) function used in encode object section 63 | - ~JSON-FM Array 64 | - update #List ( value ) function used in encode value section 65 | - ~FM-JSON { value } 66 | - fix handling of LF and CRLF returns/line endings 67 | - accommodate numbers encoded with GetAsNumber 68 | - return an error if an unknown GetAs... function is detected 69 | - prepend decimals with a 0, as required by JSON standard 70 | - ~FM-JSON { object } 71 | - process object as ¶ delimited list instead of a return delimited list, which didn't work for Char(10) 72 | - this is now the same method of processing as #Get ( parameters ; name ) function uses 73 | - ~JSON-FM Next { character } 74 | - add space before "instead of" 75 | - JSON: READ ME 76 | - update documentation 77 | 78 | 79 | # 1.0.0 # 80 | 81 | - initial release -------------------------------------------------------------------------------- /fmdiff/standard.css: -------------------------------------------------------------------------------- 1 | body{font-size: 75%;padding: 0px 2% 0px 0px;line-height:1.4em;font-family:Verdana,Arial,Helvetica,sans-serif;} 2 | @media print{body{font-size:8pt;padding:0 0 0 48px;}} 3 | .boxHead,.boxSect,.boxCont,.boxFoot,.boxErr,.boxWarn,.boxLeg{padding-left:2%;border:1px solid #777;} 4 | .boxHead,.boxSect,.boxCont,.boxFoot,.boxErr,.boxWarn,.boxLeg,.lf{width:100%;} 5 | .boxCont,.boxErr,.boxWarn{border-top:none;} 6 | .boxCont{background-color:#cadcee;} 7 | .boxHead,.boxSect,.boxFoot{background-color:#ace;} 8 | .boxErr{background-color:#f63;} 9 | .boxLeg{background-color:#fff;border:none} 10 | .boxWarn{background-color:#fc0;} 11 | .boxSect,.boxFoot,.boxLeg{margin-top:1.4em;} 12 | .boxHead{-moz-border-radius-topleft:10px;-moz-border-radius-topright:10px;-webkit-border-top-left-radius:10px;-webkit-border-top-right-radius:10px;} 13 | .boxFoot{-moz-border-radius-bottomleft:10px;-moz-border-radius-bottomright:10px;-webkit-border-bottom-left-radius:10px;-webkit-border-bottom-right-radius:10px;} 14 | .txtHead{font-size:1.4em;line-height:1.4em;} 15 | .txtHead,.txtTit,.txtName,.l0,.lf,.boxFoot{font-weight:bold;} 16 | .l1,.l2{border-top:1px solid #ccc;} 17 | .l1{background-color:#fff;} 18 | .l2{background-color:#eee;} 19 | .lf{background-color:#090;} 20 | .italic{font-style:italic;} 21 | .c4711{float:right;width:48%;display:inline-block;vertical-align:top;} 22 | .c2{width:2%;} 23 | .c3{width:3%;} 24 | .c4{width:4%;} 25 | .c5,.c5e{width:5%;} 26 | .c6,.c6e{width:6%;} 27 | .c5e,.c6e{font-weight:bold;color:red} 28 | .c8{width:8%;} 29 | .c9{width:9%;} 30 | .c11{width:11%;} 31 | .c13{width:13%;} 32 | .c16,.c16s{width:16%;} 33 | .c16s,.id{color:#666;font-size:0.8em;font-weight:normal;} 34 | .c18{width:18%;} 35 | .c20{width:22%;} 36 | .c28{width:28%;} 37 | .c32{width:32%;} 38 | .c33{width:33%;background-color:#AAE;} 39 | .c40{width:41%;} 40 | .c50{width:52%;} 41 | .c70{width:70%;} 42 | .c80{width:80%;} 43 | .c97{width:96%;} 44 | .inl{padding-left:0.5em} 45 | .in1{padding-left:1em;} 46 | .in2{padding-left:2em;} 47 | .in3{padding-left:3em;} 48 | .in4{padding-left:4em;} 49 | .in5{padding-left:5em;} 50 | .in6{padding-left:6em;} 51 | .in7{padding-left:7em;} 52 | .in8{padding-left:8em;} 53 | .idel{background-color:#ff9f7f;} 54 | .iins{background-color:#C6E9C6;} 55 | .imod{background-color:#ffdf7f;} 56 | /*#C6E9C6.bkmod{background-color:#eee;}*/ 57 | .add,.bl,.c0,.c2,.c3,.c4,.c5,.c5e,.c6,.c6e,.c8,.c9,.c11,.c13,.c16,.c16s,.c18,.c20,.c28,.c32,.c33,.c40,.c40r,.c50,.c70,.c80,.c97,.mod,.rem,.uparr,.id,.idel,.iins,.imod{vertical-align:top;display:inline-block;} 58 | .id{float:right;} 59 | /*.boxSect,.boxCont,.boxErr,.boxWarn,.boxFoot,*/.add,.rem,.mod,.uparr,.bl,.c0,.l1,.l2,.c16,.c16s,.c32,.c33,.c50,.c40r,.c70,.c80,.c97{position:relative;} 60 | a{text-decoration:none;} 61 | a:hover[href] { background-color: #fcf61a; } 62 | .add:before{content:url('data:image/gif;base64,R0lGODlhDAAMAKIAADtgNhQgEmOgWic/I3a/a0+AR57/jwAAACH5BAAAAAAALAAAAAAMAAwAAAMdaLrcSsSxUuSiVmE3egjdwEAEAJDSZqmSIGQwnAAAOw==');} 63 | .mod:before{content:url('data:image/gif;base64,R0lGODlhDAAMAKIAACUgE9q/bT84IJWCS+/ReGBUMAAAAP/ffyH5BAAAAAAALAAAAAAMAAwAAAMaeLrc/jC2AcB4QYwAyiFF4BCCYRSEpK5seyQAOw==');} 64 | .rem:before{content:url('data:image/gif;base64,R0lGODlhDAAMAJEAAL94YD8oIP+ffwAAACH5BAAAAAAALAAAAAAMAAwAAAIPlI+py+0boowI2Guf3lwXADs=');} 65 | .uparr:before{content:url('data:image/gif;base64,R0lGODlhDAAMAKIDADtH+W+F9Ju676rM7jM++gAAAAAAAAAAACH5BAEAAAMALAAAAAAMAAwAAAMjOLrc/iMEOAQAAgZCphMclzVASADNZnZMuaKKurLgHAqyHSQAOw==');} 66 | .add,.rem,.mod,.uparr{width:12px;height:12px;top:1px;margin-right:2px;} 67 | html:not([dummy]) .css21{display:none;} 68 | /*body:nth-of-type(1) .css21{display:none;}*/ 69 | -------------------------------------------------------------------------------- /fmdiff/JSON 1.0.2.html: -------------------------------------------------------------------------------- 1 | FMDiff™ Report: “JSON 1.0.2.fmp12” - 2014-07-29 12:07:02

This browser may not honor CSS 2.1 and hence may not be capable to display this FMDiff report correctly. Please upgrade to a more recent browser version. Recommended browsers are: FireFox, Safari, or equivalent.

FMDiff™ Report: “JSON 1.0.2.fmp12”
Tool
FMDiff (v3.0.6)
Date
2014-07-29 12:07:02
Elapsed
00:00:00.018
Files
Old: JSON 1.0.1.fmp12
 
New: JSON 1.0.2.fmp12
Path
R: › JSON 1.0.1.fmp12
 
R: › JSON 1.0.2.fmp12
Created
2013-04-25 23:11:06
 
2013-04-25 23:11:06
Modified
2022-09-01 10:27:07
 
2022-09-01 15:58:14
Creator
12.0
 
12.0
Size
752.0 KiB (770048 bytes, 188 blocks)
 
916.0 KiB (937984 bytes, 229 blocks)
Used With
OS Version
Count
 
OS Version
Count
 
Windows 7
23
 
Windows 7
26
 
Windows Vista
6
 
Windows Vista
6
No apparent errors or warnings.
Differences Overview
 
Removed
 
Modified
 
Added
 
4
 
 
2
 
 
2
 
 
10
 
 Base Table “Data”
ID 8001   
Name
Data
 
Data
RecordsChangeCount
2511
 
2736
 
 Field “id”
ID 03   
Name
id
 
id
nextAutoEnterValue
79
 
102
 
 Field “expression”
ID 04   
Name
expression
 
expression
indexOptions
valueIndex
 
valueIndex, wordIndex
 
 Base Table “Test”
ID 8002   
Name
Test
 
Test
 
 Field “id”
ID 02   
Name
id
 
id
nextAutoEnterValue
114
 
146
 
 Base Table “JSONFMUnitTest”
ID 8004   
Name
JSONFMUnitTest
 
JSONFMUnitTest
 
 Field “id”
ID 02   
Name
id
 
id
nextAutoEnterValue
27
 
33
 
 Base Table “FMJSONUnitTest”
ID 8006   
Name
FMJSONUnitTest
 
FMJSONUnitTest
 
 Field “id”
ID 02   
Name
id
 
id
nextAutoEnterValue
60
 
77
 Layout “JSON-FM: UnitTest”
ID 05   
Name
JSON-FM: UnitTest
 
JSON-FM: UnitTest
modifications
103
 
110
 
 Layout “FM-JSON: UnitTest”
ID 10   
Name
FM-JSON: UnitTest
 
FM-JSON: UnitTest
modifications
109
 
127
 Custom Function “#”
ID 01   
Name
#
 
#
CalculationBytecode
Let( [anon2 = Substitute( "/*start*/" & name; ["/*start*/$$"; ""]; ["/*start*/$"; ""]; ["/*start*/"; ""] ); anon3 = GetAsText( value ); anon4 = GetAsNumber( value ); anon5 = IsValid( GetAsDate( anon3 ) ) and not( IsEmpty( anon4 ) ); anon6 = IsValid( GetAsTime( anon3 ) ) and Position( anon3; ":"; 1; 1 ) > 0 and not( IsEmpty( anon4 ) ); anon7 = Case( value = "" or value = "?"; Quote( value ); anon6 and anon5; "GetAsTimestamp ( " & Quote( value ) & " )"; anon6; "GetAsTime ( " & Quote( value ) & " )"; anon5; "GetAsDate ( " & Quote( value ) & " )"; anon3 ≠ GetAsText( anon4 ); Quote( value ); 1; anon4 ); anon8 = "$" & anon2 & " = " & anon7 & " ;¶"; anon9 = "Let ( [ " & anon8 & " ~ = \"\" ]; \"\" )"; anon10 = Case( IsEmpty( anon2 ) or Position( anon2; ¶; 1; 1 ) ≠ 0; 11; not( IsValidExpression( anon9 ) ); 1200 )]; If( anon10; "/* Error " & anon10 & " name: " & Quote( Substitute( name; ["*/"; "\*\/"]; ["/*"; "\/\*"] ) ) & " value: " & Quote( Substitute( value; ["*/"; "\*\/"]; ["/*"; "\/\*"] ) ) & " */" & ¶; anon8 ) )
 
Let( [anon2 = Substitute( "/*start*/" & name; ["/*start*/$$"; ""]; ["/*start*/$"; ""]; ["/*start*/"; ""] ); anon3 = GetAsText( value + 1 ); anon4 = GetAsNumber( value ); anon5 = Case( value = "" or value = "?" or anon4 = "?"; Quote( value ); GetAsText( GetAsTimestamp( value ) + 1 ) = anon3; "GetAsTimestamp ( " & Quote( value ) & " )"; GetAsText( GetAsTime( value ) + 1 ) = anon3; "GetAsTime ( " & Quote( value ) & " )"; GetAsText( GetAsDate( value ) + 1 ) = anon3; "GetAsDate ( " & Quote( value ) & " )"; value ≠ anon4; Quote( value ); 1; anon4 ); anon6 = "$" & anon2 & " = " & anon5 & " ;¶"; anon7 = "Let ( [ " & anon6 & " ~ = \"\" ]; \"\" )"; anon8 = Case( IsEmpty( anon2 ) or Position( anon2; ¶; 1; 1 ) ≠ 0; 11; not( IsValidExpression( anon7 ) ); 1200 )]; If( anon8; "/* Error " & anon8 & " name: " & Quote( Substitute( name; ["*/"; "\*\/"]; ["/*"; "\/\*"] ) ) & " value: " & Quote( Substitute( value; ["*/"; "\*\/"]; ["/*"; "\/\*"] ) ) & " */" & ¶; anon6 ) )
modifications
3
 
4
 
 Custom Function “#List”
ID 06   
Name
#List
 
#List
CalculationBytecode
Let( [anon1 = GetAsText( value ); anon2 = GetAsNumber( value ); anon3 = IsValid( GetAsDate( anon1 ) ) and not( IsEmpty( anon2 ) ); anon4 = IsValid( GetAsTime( anon1 ) ) and Position( anon1; ":"; 1; 1 ) > 0 and not( IsEmpty( anon2 ) ); anon5 = Case( value = "" or value = "?"; Quote( value ); anon4 and anon3; "GetAsTimestamp ( " & Quote( value ) & " )"; anon4; "GetAsTime ( " & Quote( value ) & " )"; anon3; "GetAsDate ( " & Quote( value ) & " )"; anon1 ≠ GetAsText( anon2 ); Substitute( Quote( value ); [Char( 10 ); "\" & Char ( 10 ) & \""]; [Char( 8232 ); "\" & Char ( 8232 ) & \""]; [Char( 8233 ); "\" & Char ( 8233 ) & \""] ); 1; anon2 )]; Case( IsValidExpression( anon5 ); anon5 & ¶; 1; "/* Error " & 1200 & " value: " & Quote( Substitute( value; ["*/"; "\*\/"]; ["/*"; "\/\*"] ) ) & " */" & ¶ ) )
 
Let( [anon1 = GetAsText( value + 1 ); anon2 = GetAsNumber( value ); anon3 = Case( value = "" or value = "?" or anon2 = "?"; Quote( value ); GetAsText( GetAsTimestamp( value ) + 1 ) = anon1; "GetAsTimestamp ( " & Quote( value ) & " )"; GetAsText( GetAsTime( value ) + 1 ) = anon1; "GetAsTime ( " & Quote( value ) & " )"; GetAsText( GetAsDate( value ) + 1 ) = anon1; "GetAsDate ( " & Quote( value ) & " )"; value ≠ anon2; Substitute( Quote( value ); [Char( 10 ); "\" & Char ( 10 ) & \""]; [Char( 8232 ); "\" & Char ( 8232 ) & \""]; [Char( 8233 ); "\" & Char ( 8233 ) & \""] ); 1; anon2 )]; Case( IsValidExpression( anon3 ); anon3 & ¶; 1; "/* Error " & 1200 & " value: " & Quote( Substitute( value; ["*/"; "\*\/"]; ["/*"; "\/\*"] ) ) & " */" & ¶ ) )
modifications
1
 
2
 Script “JSON: Private”
ID 02   
Name
JSON: Private
 
JSON: Private
modifications
31
 
33
 
 Script “~JSON-FM Array”
ID 0B   
Name
~JSON-FM Array
 
~JSON-FM Array
modifications
50
 
52
1
# ###############################################################################
 
# ###############################################################################
2
# PURPOSE:
 
# PURPOSE:
3
# Parse an array value.
 
# Parse an array value.
4
#
 
#
5
# PARAMETERS: none
 
# PARAMETERS: none
6
#
 
#
7
# RETURNS:
 
# RETURNS:
8
# array
 
# array
9
#
 
#
10
# REVISIONS:
 
# REVISIONS:
11
# 2014-MAR-30 Daniel Smith - update #List ( value ) function used in encode value section 2013-AUG-06 Daniel Smith dansmith65@gmail.com - created
 
# 2014-MAR-30 Daniel Smith - update #List ( value ) function used in encode value section to version date 2014-06-06 2014-MAR-30 Daniel Smith - update #List ( value ) function used in encode value section 2013-AUG-06 Daniel Smith dansmith65@gmail.com - created
12
# ###############################################################################
 
# ###############################################################################
13
#
 
#
14
#
 
#
15
Set Variable[ $array ]
 
Set Variable[ $array ]
16
#
 
#
17
#
 
#
18
If[ $$~JSON.CH = "[" ]
 
If[ $$~JSON.CH = "[" ]
19
Perform Script[ “~JSON-FM Next { character }”; Parameter: "[" ]
 
Perform Script[ “~JSON-FM Next { character }”; Parameter: "[" ]
20
Perform Script[ “~JSON-FM White” ]
 
Perform Script[ “~JSON-FM White” ]
21
If[ $$~JSON.CH = "]" ]
 
If[ $$~JSON.CH = "]" ]
22
Perform Script[ “~JSON-FM Next { character }”; Parameter: "]" ]
 
Perform Script[ “~JSON-FM Next { character }”; Parameter: "]" ]
23
Exit Script[ Result: $array ]
 
Exit Script[ Result: $array ]
24
End If
 
End If
25
#
 
#
26
Loop
 
Loop
27
Exit Loop If[ IsEmpty( $$~JSON.CH ) ]
 
Exit Loop If[ IsEmpty( $$~JSON.CH ) ]
28
Perform Script[ “~JSON-FM Value” ]
 
Perform Script[ “~JSON-FM Value” ]
29
# encode value
 
# encode value
30
Set Variable[ $array; Value: $array & Let( anon0 = Get( ScriptResult ); Let( [anon1 = GetAsText( anon0 ); anon2 = GetAsNumber( anon0 ); anon3 = IsValid( GetAsDate( anon1 ) ) and not( IsEmpty( anon2 ) ); anon4 = IsValid( GetAsTime( anon1 ) ) and Position( anon1; ":"; 1; 1 ) > 0 and not( IsEmpty( anon2 ) ); anon5 = Case( anon0 = "" or anon0 = "?"; Quote( anon0 ); anon4 and anon3; "GetAsTimestamp ( " & Quote( anon0 ) & " )"; anon4; "GetAsTime ( " & Quote( anon0 ) & " )"; anon3; "GetAsDate ( " & Quote( anon0 ) & " )"; anon1 GetAsText( anon2 ); Substitute( Quote( anon0 ); [Char( 10 ); "\" & Char ( 10 ) & \""]; [Char( 8232 ); "\" & Char ( 8232 ) & \""]; [Char( 8233 ); "\" & Char ( 8233 ) & \""] ); 1; anon2 )]; Case( IsValidExpression( anon5 ); anon5 & ¶; 1; "/* Error " & 1200 & " value: " & Quote( Substitute( anon0; ["*/"; "\*\/"]; ["/*"; "\/\*"] ) ) & " */" & ¶ ) ) ) ]
 
Set Variable[ $array; Value: $array & Let( anon0 = Get( ScriptResult ); Let( [anon1 = GetAsText( anon0 + 1 ); anon2 = GetAsNumber( anon0 ); anon3 = Case( anon0 = "" or anon0 = "?" or anon2 = "?"; Quote( anon0 ); GetAsText( GetAsTimestamp( anon0 ) + 1 ) = anon1; "GetAsTimestamp ( " & Quote( anon0 ) & " )"; GetAsText( GetAsTime( anon0 ) + 1 ) = anon1; "GetAsTime ( " & Quote( anon0 ) & " )"; GetAsText( GetAsDate( anon0 ) + 1 ) = anon1; "GetAsDate ( " & Quote( anon0 ) & " )"; anon0 anon2; Substitute( Quote( anon0 ); [Char( 10 ); "\" & Char ( 10 ) & \""]; [Char( 8232 ); "\" & Char ( 8232 ) & \""]; [Char( 8233 ); "\" & Char ( 8233 ) & \""] ); 1; anon2 )]; Case( IsValidExpression( anon3 ); anon3 & ¶; 1; "/* Error " & 1200 & " value: " & Quote( Substitute( anon0; ["*/"; "\*\/"]; ["/*"; "\/\*"] ) ) & " */" & ¶ ) ) ) ]
31
Perform Script[ “~JSON-FM White” ]
 
Perform Script[ “~JSON-FM White” ]
32
If[ $$~JSON.CH = "]" ]
 
If[ $$~JSON.CH = "]" ]
33
Perform Script[ “~JSON-FM Next { character }”; Parameter: "]" ]
 
Perform Script[ “~JSON-FM Next { character }”; Parameter: "]" ]
34
Exit Script[ Result: $array ]
 
Exit Script[ Result: $array ]
35
End If
 
End If
36
Perform Script[ “~JSON-FM Next { character }”; Parameter: "," ]
 
Perform Script[ “~JSON-FM Next { character }”; Parameter: "," ]
37
Perform Script[ “~JSON-FM White” ]
 
Perform Script[ “~JSON-FM White” ]
38
End Loop
 
End Loop
39
End If
 
End If
40
#
 
#
41
Perform Script[ “~JSON-FM Error { message }”; Parameter: "Bad array" ]
 
Perform Script[ “~JSON-FM Error { message }”; Parameter: "Bad array" ]
42
Exit Script[ Result: Get( ScriptResult ) ]
 
Exit Script[ Result: Get( ScriptResult ) ]
43
#
 
#
 
 Script “~JSON-FM Object”
ID 0E   
Name
~JSON-FM Object
 
~JSON-FM Object
modifications
69
 
71
1
# ###############################################################################
 
# ###############################################################################
2
# PURPOSE:
 
# PURPOSE:
3
# Parse an object value.
 
# Parse an object value.
4
#
 
#
5
# PARAMETERS: none
 
# PARAMETERS: none
6
#
 
#
7
# RETURNS:
 
# RETURNS:
8
# object
 
# object
9
#
 
#
10
# REVISIONS:
 
# REVISIONS:
11
# 2014-MAR-30 Daniel Smith - update # ( name ; value ) function used in encode object section 2013-AUG-06 Daniel Smith dansmith65@gmail.com - created
 
# 2014-JUL-29 Daniel Smith - update # ( name ; value ) function used in encode object section to version date 2014-06-06 2014-MAR-30 Daniel Smith - update # ( name ; value ) function used in encode object section 2013-AUG-06 Daniel Smith dansmith65@gmail.com - created
12
# ###############################################################################
 
# ###############################################################################
13
#
 
#
14
#
 
#
15
Set Variable[ $key ]
 
Set Variable[ $key ]
16
Set Variable[ $object ]
 
Set Variable[ $object ]
17
#
 
#
18
#
 
#
19
If[ $$~JSON.CH = "{" ]
 
If[ $$~JSON.CH = "{" ]
20
Perform Script[ “~JSON-FM Next { character }”; Parameter: "{" ]
 
Perform Script[ “~JSON-FM Next { character }”; Parameter: "{" ]
21
Perform Script[ “~JSON-FM White” ]
 
Perform Script[ “~JSON-FM White” ]
22
If[ $$~JSON.CH = "}" ]
 
If[ $$~JSON.CH = "}" ]
23
Perform Script[ “~JSON-FM Next { character }”; Parameter: "}" ]
 
Perform Script[ “~JSON-FM Next { character }”; Parameter: "}" ]
24
Exit Script[ Result: $object ]
 
Exit Script[ Result: $object ]
25
End If
 
End If
26
#
 
#
27
Loop
 
Loop
28
Exit Loop If[ IsEmpty( $$~JSON.CH ) ]
 
Exit Loop If[ IsEmpty( $$~JSON.CH ) ]
29
Perform Script[ “~JSON-FM String” ]
 
Perform Script[ “~JSON-FM String” ]
30
Set Variable[ $key; Value: Get( ScriptResult ) ]
 
Set Variable[ $key; Value: Get( ScriptResult ) ]
31
# remove characters that are invalid for use in a let variable
 
# remove characters that are invalid for use in a let variable
32
Set Variable[ $key; Value: Substitute( $key; [","; ""]; ["+"; ""]; ["-"; ""]; ["*"; ""]; ["//"; ""]; ["^"; ""]; ["&"; ""]; ["="; ""]; ["≠"; ""]; [">"; ""]; ["<"; ""]; ["("; ""]; [")"; ""]; ["["; ""]; ["]"; ""]; ["{"; ""]; ["}"; ""]; ["\""; ""]; [";"; ""]; [":"; ""] ) ]
 
Set Variable[ $key; Value: Substitute( $key; [","; ""]; ["+"; ""]; ["-"; ""]; ["*"; ""]; ["//"; ""]; ["^"; ""]; ["&"; ""]; ["="; ""]; ["≠"; ""]; [">"; ""]; ["<"; ""]; ["("; ""]; [")"; ""]; ["["; ""]; ["]"; ""]; ["{"; ""]; ["}"; ""]; ["\""; ""]; [";"; ""]; [":"; ""] ) ]
33
Perform Script[ “~JSON-FM White” ]
 
Perform Script[ “~JSON-FM White” ]
34
Perform Script[ “~JSON-FM Next { character }”; Parameter: ":" ]
 
Perform Script[ “~JSON-FM Next { character }”; Parameter: ":" ]
35
If[ False ]
 
If[ False ]
36
# when using the custom functions available at the link below to access data, this section is not needed since new key's replace old keys http://filemakerstandards.org/x/loEI
 
# when using the custom functions available at the link below to access data, this section is not needed since new key's replace old keys http://filemakerstandards.org/x/loEI
37
Perform Script[ “~JSON-FM Error { message }”; Parameter: "Duplicate key " & Quote( $key ) ]
 
Perform Script[ “~JSON-FM Error { message }”; Parameter: "Duplicate key " & Quote( $key ) ]
38
Exit Script[ Result: Get( ScriptResult ) ]
 
Exit Script[ Result: Get( ScriptResult ) ]
39
End If
 
End If
40
Perform Script[ “~JSON-FM Value” ]
 
Perform Script[ “~JSON-FM Value” ]
41
# encode object
 
# encode object
42
Set Variable[ $object; Value: $object & Let( [anon0 = $key; anon1 = Get( ScriptResult )]; Let( [anon2 = Substitute( "/*start*/" & anon0; ["/*start*/$$"; ""]; ["/*start*/$"; ""]; ["/*start*/"; ""] ); anon3 = GetAsText( anon1 ); anon4 = GetAsNumber( anon1 ); anon5 = IsValid( GetAsDate( anon3 ) ) and not( IsEmpty( anon4 ) ); anon6 = IsValid( GetAsTime( anon3 ) ) and Position( anon3; ":"; 1; 1 ) > 0 and not( IsEmpty( anon4 ) ); anon7 = Case( anon1 = "" or anon1 = "?"; Quote( anon1 ); anon6 and anon5; "GetAsTimestamp ( " & Quote( anon1 ) & " )"; anon6; "GetAsTime ( " & Quote( anon1 ) & " )"; anon5; "GetAsDate ( " & Quote( anon1 ) & " )"; anon3 GetAsText( anon4 ); Quote( anon1 ); 1; anon4 ); anon8 = "$" & anon2 & " = " & anon7 & " ;¶"; anon9 = "Let ( [ " & anon8 & " ~ = \"\" ]; \"\" )"; anon10 = Case( IsEmpty( anon2 ) or Position( anon2; ¶; 1; 1 ) ≠ 0; 11; not( IsValidExpression( anon9 ) ); 1200 )]; If( anon10; "/* Error " & anon10 & " name: " & Quote( Substitute( anon0; ["*/"; "\*\/"]; ["/*"; "\/\*"] ) ) & " value: " & Quote( Substitute( anon1; ["*/"; "\*\/"]; ["/*"; "\/\*"] ) ) & " */" & ¶; anon8 ) ) ) ]
 
Set Variable[ $object; Value: $object & Let( [anon0 = $key; anon1 = Get( ScriptResult )]; Let( [anon2 = Substitute( "/*start*/" & anon0; ["/*start*/$$"; ""]; ["/*start*/$"; ""]; ["/*start*/"; ""] ); anon3 = GetAsText( anon1 + 1 ); anon4 = GetAsNumber( anon1 ); anon5 = Case( anon1 = "" or anon1 = "?" or anon4 = "?"; Quote( anon1 ); GetAsText( GetAsTimestamp( anon1 ) + 1 ) = anon3; "GetAsTimestamp ( " & Quote( anon1 ) & " )"; GetAsText( GetAsTime( anon1 ) + 1 ) = anon3; "GetAsTime ( " & Quote( anon1 ) & " )"; GetAsText( GetAsDate( anon1 ) + 1 ) = anon3; "GetAsDate ( " & Quote( anon1 ) & " )"; anon1 anon4; Quote( anon1 ); 1; anon4 ); anon6 = "$" & anon2 & " = " & anon5 & " ;¶"; anon7 = "Let ( [ " & anon6 & " ~ = \"\" ]; \"\" )"; anon8 = Case( IsEmpty( anon2 ) or Position( anon2; ¶; 1; 1 ) ≠ 0; 11; not( IsValidExpression( anon7 ) ); 1200 )]; If( anon8; "/* Error " & anon8 & " name: " & Quote( Substitute( anon0; ["*/"; "\*\/"]; ["/*"; "\/\*"] ) ) & " value: " & Quote( Substitute( anon1; ["*/"; "\*\/"]; ["/*"; "\/\*"] ) ) & " */" & ¶; anon6 ) ) ) ]
43
Perform Script[ “~JSON-FM White” ]
 
Perform Script[ “~JSON-FM White” ]
44
If[ $$~JSON.CH = "}" ]
 
If[ $$~JSON.CH = "}" ]
45
Perform Script[ “~JSON-FM Next { character }”; Parameter: "}" ]
 
Perform Script[ “~JSON-FM Next { character }”; Parameter: "}" ]
46
Exit Script[ Result: $object ]
 
Exit Script[ Result: $object ]
47
End If
 
End If
48
Perform Script[ “~JSON-FM Next { character }”; Parameter: "," ]
 
Perform Script[ “~JSON-FM Next { character }”; Parameter: "," ]
49
Perform Script[ “~JSON-FM White” ]
 
Perform Script[ “~JSON-FM White” ]
50
End Loop
 
End Loop
51
End If
 
End If
52
#
 
#
53
Perform Script[ “~JSON-FM Error { message }”; Parameter: "Bad object" ]
 
Perform Script[ “~JSON-FM Error { message }”; Parameter: "Bad object" ]
54
Exit Script[ Result: Get( ScriptResult ) ]
 
Exit Script[ Result: Get( ScriptResult ) ]
55
#
 
#
 
 Script “App - JSON”
ID 18   
Name
App - JSON
 
App - JSON
modifications
27
 
31
 
 Script “JSON: READ ME”
ID 1F   
Name
JSON: READ ME
 
JSON: READ ME
modifications
45
 
52
1
# ################################################################################
 
# ################################################################################
2
#
 
#
3
#
 
#
4
# JSON
 
# JSON
5
#
 
#
6
# Created by Daniel Smith, dansmith65@gmail.com
 
# Created by Daniel Smith, dansmith65@gmail.com
7
#
 
#
8
# Provides native support for JSON in FileMaker.
 
# Provides native support for JSON in FileMaker.
9
#
 
#
10
 
 
# http://www.modularfilemaker.org/module/json/
11
#
 
#
12
 
 
#
13
# ################################################################################
 
# ################################################################################
14
#
 
#
15
#
 
#
16
#
 
#
17
# REQUIRES
 
# REQUIRES
18
# No strict dependencies, see installation section for optional dependencies.
 
# No strict dependencies, see installation section for optional dependencies.
19
#
 
#
20
#
 
#
21
#
 
#
22
# INTEGRATION
 
# INTEGRATION
23
# ( it's wise to check the Import.log file for errors, as you add elements to your database )
 
# ( it's wise to check the Import.log file for errors, as you add elements to your database )
24
# 1. import module script folder
 
# 1. import module script folder
25
#
 
#
26
# 2. review all scripts in the module Config folder, adjust as necessary
 
# 2. review all scripts in the module Config folder, adjust as necessary
27
#
 
#
28
# 3. import custom functions:
 
# 3. import custom functions:
29
# for retrieving values from parsed JSON:
 
# for retrieving values from parsed JSON:
30
# (these are optional since you could manually extract the values)
 
# (these are optional since you could manually extract the values)
31
# - [optional] #Get
 
# - [optional] #Get
32
# - [optional] #ListGet
 
# - [optional] #ListGet
33
# - [optional] #GetNameList (is helpful when you want to iterate through all objects)
 
# - [optional] #GetNameList (is helpful when you want to iterate through all objects)
34
# for creating FileMaker Let notation in the format the FM-JSON script expects:
 
# for creating FileMaker Let notation in the format the FM-JSON script expects:
35
# (these are optional since you could manually encode the values)
 
# (these are optional since you could manually encode the values)
36
# - [optional] #
 
# - [optional] #
37
# - [optional] #List
 
# - [optional] #List
38
# Other useful custom functions in this suite can be found in the #Parameters module http://www.modularfilemaker.org/2013/07/parameters/
 
# Other useful custom functions in this suite can be found in the #Parameters module http://www.modularfilemaker.org/module/parameters/
39
#
 
#
40
#
 
#
41
#
 
#
42
# INSTRUCTIONS FOR USE
 
# INSTRUCTIONS FOR USE
43
# Please refer to the "FM > JSON: Sandbox" section of the demo file for examples of how to access data from a parsed json string.
 
# Please refer to the "FM > JSON: Sandbox" section of the demo file for examples of how to access data from a parsed json string.
44
# The unit tests serve as documentation for the values you should expect to get from this module.
 
# The unit tests serve as documentation for the values you should expect to get from this module.
45
#
 
#
46
#
 
#
47
#
 
#
48
# KNOWN ISSUES
 
# KNOWN ISSUES
49
# 1. Object name's in JSON do not have any restrictions on the characters that can be used; FileMaker Let Notation does. The JSON-FM scripts removes invalid characters from object names, so you may need to account for this when accessing objects. See unit test titled "object name with invalid characters" for an example of this. This issue could be resolved by using an encoding/decoding format that fully escapes an object name, like the one available here: http://sixfriedrice.com/wp/passing-multiple-parameters-to-scripts-advanced/. To make this change, two scripts need to be modified: 1. ~JSON-FM Array Set Variable step followed by the comment "encode value" 2. ~JSON-FM Object Set Variable step followed by the comment "encode object" Set Variable step followed by the comment "remove characters that are invalid for use in a let variable" The FM-JSON scripts do not provide the ability to create JSON with certain character in an objects name, it is restricted to the name being a valid let variable name. These scripts are completely dependent on the storage format used, so to implement a storage format that allows for any name in an object, you would need to modify most (if not all) of the FM-JSON scripts.
 
# 1. Object name's in JSON do not have any restrictions on the characters that can be used; FileMaker Let Notation does. The JSON-FM scripts removes invalid characters from object names, so you may need to account for this when accessing objects. See unit test titled "object name with invalid characters" for an example of this. This issue could be resolved by using an encoding/decoding format that fully escapes an object name, like the one available here: http://sixfriedrice.com/wp/passing-multiple-parameters-to-scripts-advanced/. To make this change, two scripts need to be modified: 1. ~JSON-FM Array Set Variable step followed by the comment "encode value" 2. ~JSON-FM Object Set Variable step followed by the comment "encode object" Set Variable step followed by the comment "remove characters that are invalid for use in a let variable" The FM-JSON scripts do not provide the ability to create JSON with certain character in an objects name, it is restricted to the name being a valid let variable name. These scripts are completely dependent on the storage format used, so to implement a storage format that allows for any name in an object, you would need to modify most (if not all) of the FM-JSON scripts.
50
# 2. True/False are not used - only 1/0. - when converting from FM-JSON
 
# 2. True/False are not used - only 1/0. - when converting from FM-JSON
51
# 3. null is used instead of empty string - when converting from FM-JSON
 
# 3. null is used instead of empty string - when converting from FM-JSON
52
#
 
#
53
#
 
#
54
#
 
#
55
 
 
# UPGRADE PROCESS
56
 
 
# ( use these instructions when you already have the JSON module installed, but want to upgrade to the latest version )
57
 
 
# 1. Review the change log in the "JSON: Version X.X.X" script for version-specific update steps.
58
 
 
# 2. Delete the "JSON: Private" script folder
59
 
 
# 3. Import the "JSON: Private" script folder from the updated module
60
 
 
# 4. Edit every script in the "JSON: Public" folder:
61
 
 
# a. delete all script steps
62
 
 
# b. copy/paste all script steps from the same script in the updated module
63
 
 
#
64
 
 
#
65
 
 
#
66
# LICENSE:
 
# LICENSE:
67
# The MIT License (MIT) Copyright (c) 2014 Daniel Smith Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
# The MIT License (MIT) Copyright (c) 2014 Daniel Smith Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
68
#
 
#
 
 Script “JSON: Version 1.0.2”
ID 26   
Name
JSON: Version 1.0.1
 
JSON: Version 1.0.2
modifications
32
 
40
1
# ###############################################################################
 
# ###############################################################################
2
# PURPOSE:
 
# PURPOSE:
3
# Return the version number of this module.
 
# Return the version number of this module.
4
#
 
#
5
# RETURNS:
 
# RETURNS:
6
# version string portion of the script name
 
# version string portion of the script name
7
#
 
#
8
# NOTES:
 
# NOTES:
9
# http://filemakerstandards.org/display/bp/Default+scripts
 
# http://filemakerstandards.org/display/bp/Default+scripts
10
# This guideline was heavily influenced by http://semver.org/spec/v2.0.0-rc.1.html
 
# This guideline was heavily influenced by http://semver.org/spec/v2.0.0-rc.1.html
11
# Changelog: Summary is formatted with markdown: http://daringfireball.net/projects/markdown/ - use different header 'tag' (#'s) depending on the version being incremented Major: H1 Minor: H2 Patch: H3
 
# Changelog: Summary is formatted with markdown: http://daringfireball.net/projects/markdown/ - use different header 'tag' (#'s) depending on the version being incremented Major: H1 Minor: H2 Patch: H3
12
# ###############################################################################
 
# ###############################################################################
13
Set Variable[ $scriptResult; Value: Let( [anon0 = Get( ScriptName ); anon1 = Left( Filter( anon0; "0123456789" ); 1 ); anon2 = Position( anon0; anon1; 1; 1 )]; Right( anon0; Length( anon0 ) - anon2 + 1 ) ) ]
 
Set Variable[ $scriptResult; Value: Let( [anon0 = Get( ScriptName ); anon1 = Left( Filter( anon0; "0123456789" ); 1 ); anon2 = Position( anon0; anon1; 1; 1 )]; Right( anon0; Length( anon0 ) - anon2 + 1 ) ) ]
14
Exit Script[ Result: $scriptResult ]
 
Exit Script[ Result: $scriptResult ]
15
#
 
#
16
# MAJOR.MINOR.PATCH{-PRERELEASE}{+}
 
# MAJOR.MINOR.PATCH{-PRERELEASE}{+}
17
# MAJOR: Arbitrarily defined by the developer, but must introduce significant change to either the feature set, or the internal method of processing.
 
# MAJOR: Arbitrarily defined by the developer, but must introduce significant change to either the feature set, or the internal method of processing.
18
# MINOR: New features. Should be incremented whenever a new feature is added.
 
# MINOR: New features. Should be incremented whenever a new feature is added.
19
# PATCH: Bug fixes. Should not introduce new features (unless the lack of that feature can be considered a bug).
 
# PATCH: Bug fixes. Should not introduce new features (unless the lack of that feature can be considered a bug).
20
# {-PRERELEASE} OPTIONAL A pre-release version MAY be denoted by appending a dash and a series of dot separated identifiers immediately following the patch version. Identifiers MUST be comprised of only ASCII alphanumerics and dash [0-9A-Za-z-]. Pre-release versions satisfy but have a lower precedence than the associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92. This value can be compaired as text in FileMaker, and the following will be true: "alpha" < "beta" and "alpha" < "rc" and "beta" < "rc".
 
# {-PRERELEASE} OPTIONAL A pre-release version MAY be denoted by appending a dash and a series of dot separated identifiers immediately following the patch version. Identifiers MUST be comprised of only ASCII alphanumerics and dash [0-9A-Za-z-]. Pre-release versions satisfy but have a lower precedence than the associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92. This value can be compaired as text in FileMaker, and the following will be true: "alpha" < "beta" and "alpha" < "rc" and "beta" < "rc".
21
# {+} OPTIONAL If the file has been modified since the version was last incremented, and the version does not need to be incremented yet (still under development), append the version string with a +.
 
# {+} OPTIONAL If the file has been modified since the version was last incremented, and the version does not need to be incremented yet (still under development), append the version string with a +.
22
#
 
#
23
# These guidelines should be followed:
 
# These guidelines should be followed:
24
# Use decimal separated text to store the version.
 
# Use decimal separated text to store the version.
25
# When evaluating the version, MUST NOT convert the entire text to a number. Each decimal separated section must be evaluated individually, and in order. Here is a possible method of doing so: Let ( [ ver = "1.2.21" ; // extract pre-release version string ver = Substitute ( ver ; "-" ; ¶ ) ; preRelease = GetValue ( ver ; 2 ) ; // extract normal version string ver = GetValue ( ver ; 1 ) ; ver = Substitute ( ver ; "." ; ¶ ) ; major = GetAsNumber ( GetValue ( ver ; 1 ) ) ; minor = GetAsNumber ( GetValue ( ver ; 2 ) ) ; patch = GetAsNumber ( GetValue ( ver ; 3 ) ) ] ; // evaluate version Case ( major = 0 ; "initial development" ; major = 1 ; "first public release" ) )
 
# When evaluating the version, MUST NOT convert the entire text to a number. Each decimal separated section must be evaluated individually, and in order. Here is a possible method of doing so: Let ( [ ver = "1.2.21" ; // extract pre-release version string ver = Substitute ( ver ; "-" ; ¶ ) ; preRelease = GetValue ( ver ; 2 ) ; // extract normal version string ver = GetValue ( ver ; 1 ) ; ver = Substitute ( ver ; "." ; ¶ ) ; major = GetAsNumber ( GetValue ( ver ; 1 ) ) ; minor = GetAsNumber ( GetValue ( ver ; 2 ) ) ; patch = GetAsNumber ( GetValue ( ver ; 3 ) ) ] ; // evaluate version Case ( major = 0 ; "initial development" ; major = 1 ; "first public release" ) )
26
# Summarize the changes of each version in a single comment step below. This should be a brief overview of the changes, whereas the Changelog: Detailed script contains the detailed daily changes.
 
# Summarize the changes of each version in a single comment step below. This should be a brief overview of the changes, whereas the Changelog: Detailed script contains the detailed daily changes.
27
#
 
#
28
#
 
#
29
# ==============================================================================
 
# ==============================================================================
30
# CHANGELOG: SUMMARY
 
# CHANGELOG: SUMMARY
31
# ==============================================================================
 
# ==============================================================================
32
#
 
#
33
# ## 1.0.1 ## - fix Issue #1 and #2 from GitHub - modify scripts: - JSON: Changelog: Detailed - deleted, will store list of all changes in the version script instead - ~JSON-FM Object - update # ( name ; value ) function used in encode object section - ~JSON-FM Array - update #List ( value ) function used in encode value section - ~FM-JSON { value } - fix handling of LF and CRLF returns/line endings - accommodate numbers encoded with GetAsNumber - return an error if an unknown GetAs... function is detected - prepend decimals with a 0, as required by JSON standard - ~FM-JSON { object } - process object as ¶ delimited list instead of a return delimited list, which didn't work for Char(10) - this is now the same method of processing as #Get ( parameters ; name ) function uses - ~JSON-FM Next { character } - add space before "instead of" - JSON: READ ME - update documentation
 
# ### 1.0.2 ### - modify scripts: - ~FM-JSON { value } - update test that differentiates an array from a string - previously, a quoted number was interpreted as an array - ~JSON-FM Object - update # ( name ; value ) function used in encode object section to version date 2014-06-06 - ~JSON-FM Array - update #List ( value ) function used in encode value section to version date 2014-06-06 - JSON: READ ME - add "UPGRADE PROCESS" section
34
 
 
# ### 1.0.1 ### - fix Issue #1 and #2 from GitHub - modify scripts: - JSON: Changelog: Detailed - deleted, will store list of all changes in the version script instead - ~JSON-FM Object - update # ( name ; value ) function used in encode object section - ~JSON-FM Array - update #List ( value ) function used in encode value section - ~FM-JSON { value } - fix handling of LF and CRLF returns/line endings - accommodate numbers encoded with GetAsNumber - return an error if an unknown GetAs... function is detected - prepend decimals with a 0, as required by JSON standard - ~FM-JSON { object } - process object as ¶ delimited list instead of a return delimited list, which didn't work for Char(10) - this is now the same method of processing as #Get ( parameters ; name ) function uses - ~JSON-FM Next { character } - add space before "instead of" - JSON: READ ME - update documentation
35
# # 1.0.0 # - initial release
 
# # 1.0.0 # - initial release
36
#
 
#
 
 Script “JSON-FM”
ID 31   
Name
JSON-FM
 
JSON-FM
modifications
18
 
19
PrivilegesF0
[8 bytes]
 
[8 bytes]
 
 Script “FM-JSON”
ID 36   
Name
FM-JSON
 
FM-JSON
modifications
5
 
6
PrivilegesF0
[8 bytes]
 
[8 bytes]
 
 Script “~FM-JSON { value }”
ID 3B   
Name
~FM-JSON { value }
 
~FM-JSON { value }
modifications
102
 
103
1
# ###############################################################################
 
# ###############################################################################
2
# PURPOSE:
 
# PURPOSE:
3
# Convert a value into JSON. The value can be let notation, array, or a single value ( text, date, time, timestamp).
 
# Convert a value into JSON. The value can be let notation, array, or a single value ( text, date, time, timestamp).
4
#
 
#
5
# PARAMETERS:
 
# PARAMETERS:
6
# value | object, array, or single value
 
# value | object, array, or single value
7
#
 
#
8
# RETURNS:
 
# RETURNS:
9
# JSON encoded text.
 
# JSON encoded text.
10
#
 
#
11
# REVISIONS:
 
# REVISIONS:
12
# 2014-MAR-30 Daniel Smith - fix handling of LF and CRLF returns/line endings 2014-FEB-20 Daniel Smith dansmith65@gmail.com - accommodate numbers encoded with GetAsNumber - return an error if an unknown GetAs... function is detected - prepend decimals with a 0, as required by JSON standard 2013-AUG-06 Daniel Smith dansmith65@gmail.com - created
 
# 2014-JUL-29 Daniel Smith - update test that differentiates an array from a string - previously, a quoted number was interpreted as an array 2014-MAR-30 Daniel Smith - fix handling of LF and CRLF returns/line endings 2014-FEB-20 Daniel Smith dansmith65@gmail.com - accommodate numbers encoded with GetAsNumber - return an error if an unknown GetAs... function is detected - prepend decimals with a 0, as required by JSON standard 2013-AUG-06 Daniel Smith dansmith65@gmail.com - created
13
# ###############################################################################
 
# ###############################################################################
14
#
 
#
15
#
 
#
16
Set Variable[ $value; Value: Trim( Get( ScriptParameter ) ) ]
 
Set Variable[ $value; Value: Trim( Get( ScriptParameter ) ) ]
17
Set Variable[ $firstChar; Value: Left( $value; 1 ) ]
 
Set Variable[ $firstChar; Value: Left( $value; 1 ) ]
18
Set Variable[ $valueEvaluated; Value: Evaluate( $value ) ]
 
Set Variable[ $valueEvaluated; Value: Evaluate( $value ) ]
19
#
 
#
20
#
 
#
21
If[ ]
 
If[ ]
22
Else If[ IsEmpty( $value ) ]
 
Else If[ IsEmpty( $value ) ]
23
Set Variable[ $result; Value: "null" ]
 
Set Variable[ $result; Value: "null" ]
24
Else If[ $firstChar = "\"" ]
 
Else If[ $firstChar = "\"" ]
25
# is string, object, or array
 
# is string, object, or array
26
If[ ]
 
If[ ]
27
Else If[ IsEmpty( $valueEvaluated ) ]
 
Else If[ IsEmpty( $valueEvaluated ) ]
28
Set Variable[ $result; Value: "null" ]
 
Set Variable[ $result; Value: "null" ]
29
Else If[ IsValidExpression( "Let ( [ " & $valueEvaluated & " $! = $1 ] ; True )" ) and Left( Substitute( $valueEvaluated; [" "; ""]; ["¶"; ""] ); 1 ) = "$" ]
 
Else If[ IsValidExpression( "Let ( [ " & $valueEvaluated & " $! = $1 ] ; True )" ) and Left( Substitute( $valueEvaluated; [" "; ""]; ["¶"; ""] ); 1 ) = "$" ]
30
Perform Script[ “~FM-JSON { object }”; Parameter: $valueEvaluated ]
 
Perform Script[ “~FM-JSON { object }”; Parameter: $valueEvaluated ]
31
Set Variable[ $result; Value: Get( ScriptResult ) ]
 
Set Variable[ $result; Value: Get( ScriptResult ) ]
32
Else If[ Exact( $valueEvaluated; Char( 13 ) ) or Exact( $valueEvaluated; Char( 10 ) ) or Exact( $valueEvaluated; Char( 13 ) & Char( 10 ) ) ]
 
Else If[ Exact( $valueEvaluated; Char( 13 ) ) or Exact( $valueEvaluated; Char( 10 ) ) or Exact( $valueEvaluated; Char( 13 ) & Char( 10 ) ) ]
33
# return character(s) are mistaken for an array, so I added an exception specifically for them
 
# return character(s) are mistaken for an array, so I added an exception specifically for them
34
Perform Script[ “~FM-JSON { string }”; Parameter: $valueEvaluated ]
 
Perform Script[ “~FM-JSON { string }”; Parameter: $valueEvaluated ]
35
Set Variable[ $result; Value: Get( ScriptResult ) ]
 
Set Variable[ $result; Value: Get( ScriptResult ) ]
36
Else If[ Let( anon0 = GetValue( $valueEvaluated; 1 ); IsValidExpression( anon0 ) and ( Left( anon0; 1 ) = "\"" and Right( anon0; 1 ) = "\"" or LeftWords( anon0; 1 ) = "GetAsDate" or LeftWords( anon0; 1 ) = "GetAsTime" or LeftWords( anon0; 1 ) = "GetAsTimeStamp" or anon0 = GetAsNumber( anon0 ) ) ) ]
 
Else If[ Let( anon0 = Substitute( $valueEvaluated & Char( 3 ); [¶ & Char( 3 ); ""]; [Char( 3 ); ""]; [¶; " & "] ); IsValidExpression( anon0 ) and ( ValueCount( $valueEvaluated ) > 1 or Right( $valueEvaluated; 1 ) = ) ) ]
37
Perform Script[ “~FM-JSON ( array )”; Parameter: $valueEvaluated ]
 
Perform Script[ “~FM-JSON ( array )”; Parameter: $valueEvaluated ]
38
Set Variable[ $result; Value: Get( ScriptResult ) ]
 
Set Variable[ $result; Value: Get( ScriptResult ) ]
39
Else
 
Else
40
Perform Script[ “~FM-JSON { string }”; Parameter: $valueEvaluated ]
 
Perform Script[ “~FM-JSON { string }”; Parameter: $valueEvaluated ]
41
Set Variable[ $result; Value: Get( ScriptResult ) ]
 
Set Variable[ $result; Value: Get( ScriptResult ) ]
42
End If
 
End If
43
#
 
#
44
#
 
#
45
Else If[ $firstChar = "G" ]
 
Else If[ $firstChar = "G" ]
46
# is a date, time, or timestamp
 
# is a date, time, or timestamp
47
Set Variable[ $firstWord; Value: LeftWords( $value; 1 ) ]
 
Set Variable[ $firstWord; Value: LeftWords( $value; 1 ) ]
48
# format as ISO8601
 
# format as ISO8601
49
If[ ]
 
If[ ]
50
Else If[ $firstWord = "GetAsDate" ]
 
Else If[ $firstWord = "GetAsDate" ]
51
Set Variable[ $result; Value: "\"" & Year( $valueEvaluated ) & "-" & Right( "00" & Month( $valueEvaluated ); 2 ) & "-" & Right( "00" & Day( $valueEvaluated ); 2 ) & "\"" ]
 
Set Variable[ $result; Value: "\"" & Year( $valueEvaluated ) & "-" & Right( "00" & Month( $valueEvaluated ); 2 ) & "-" & Right( "00" & Day( $valueEvaluated ); 2 ) & "\"" ]
52
Else If[ $firstWord = "GetAsTime" ]
 
Else If[ $firstWord = "GetAsTime" ]
53
Set Variable[ $result; Value: "\"" & Hour( $valueEvaluated ) & ":" & Right( "00" & Minute( $valueEvaluated ); 2 ) & ":" & Right( "00" & Seconds( $valueEvaluated ); 2 ) & "\"" ]
 
Set Variable[ $result; Value: "\"" & Hour( $valueEvaluated ) & ":" & Right( "00" & Minute( $valueEvaluated ); 2 ) & ":" & Right( "00" & Seconds( $valueEvaluated ); 2 ) & "\"" ]
54
Else If[ $firstWord = "GetAsTimeStamp" ]
 
Else If[ $firstWord = "GetAsTimeStamp" ]
55
Set Variable[ $result; Value: "\"" & Year( $valueEvaluated ) & "-" & Right( "00" & Month( $valueEvaluated ); 2 ) & "-" & Right( "00" & Day( $valueEvaluated ); 2 ) & "T" & Hour( $valueEvaluated ) & ":" & Right( "00" & Minute( $valueEvaluated ); 2 ) & ":" & Right( "00" & Seconds( $valueEvaluated ); 2 ) & "\"" ]
 
Set Variable[ $result; Value: "\"" & Year( $valueEvaluated ) & "-" & Right( "00" & Month( $valueEvaluated ); 2 ) & "-" & Right( "00" & Day( $valueEvaluated ); 2 ) & "T" & Hour( $valueEvaluated ) & ":" & Right( "00" & Minute( $valueEvaluated ); 2 ) & ":" & Right( "00" & Seconds( $valueEvaluated ); 2 ) & "\"" ]
56
Else If[ $firstWord = "GetAsNumber" ]
 
Else If[ $firstWord = "GetAsNumber" ]
57
Set Variable[ $result; Value: Case( Left( $valueEvaluated; 2 ) = "-."; Substitute( $valueEvaluated; "-."; "-0." ); Left( $valueEvaluated; 1 ) = "."; "0" & $valueEvaluated; 1; $valueEvaluated ) ]
 
Set Variable[ $result; Value: Case( Left( $valueEvaluated; 2 ) = "-."; Substitute( $valueEvaluated; "-."; "-0." ); Left( $valueEvaluated; 1 ) = "."; "0" & $valueEvaluated; 1; $valueEvaluated ) ]
58
Else
 
Else
59
Perform Script[ “~FM-JSON Error { message }”; Parameter: "the type of value could not be determined for: " & $valueEvaluated ]
 
Perform Script[ “~FM-JSON Error { message }”; Parameter: "the type of value could not be determined for: " & $valueEvaluated ]
60
Set Variable[ $result; Value: Get( ScriptResult ) ]
 
Set Variable[ $result; Value: Get( ScriptResult ) ]
61
End If
 
End If
62
#
 
#
63
Else If[ $valueEvaluated = GetAsNumber( $valueEvaluated ) ]
 
Else If[ $valueEvaluated = GetAsNumber( $valueEvaluated ) ]
64
Set Variable[ $result; Value: Case( Left( $valueEvaluated; 2 ) = "-."; Substitute( $valueEvaluated; "-."; "-0." ); Left( $valueEvaluated; 1 ) = "."; "0" & $valueEvaluated; 1; $valueEvaluated ) ]
 
Set Variable[ $result; Value: Case( Left( $valueEvaluated; 2 ) = "-."; Substitute( $valueEvaluated; "-."; "-0." ); Left( $valueEvaluated; 1 ) = "."; "0" & $valueEvaluated; 1; $valueEvaluated ) ]
65
#
 
#
66
Else
 
Else
67
Perform Script[ “~FM-JSON Error { message }”; Parameter: "the type of value could not be determined for: " & $valueEvaluated ]
 
Perform Script[ “~FM-JSON Error { message }”; Parameter: "the type of value could not be determined for: " & $valueEvaluated ]
68
Set Variable[ $result; Value: Get( ScriptResult ) ]
 
Set Variable[ $result; Value: Get( ScriptResult ) ]
69
#
 
#
70
End If
 
End If
71
#
 
#
72
#
 
#
73
Exit Script[ Result: $result ]
 
Exit Script[ Result: $result ]
 
 Script “App - JSON: Version 1.0.1”
ID 44   
Name
App - JSON: Version 1.0.0
 
App - JSON: Version 1.0.1
modifications
13
 
15
1
# ###############################################################################
 
# ###############################################################################
2
# PURPOSE:
 
# PURPOSE:
3
# Return the version number of this application.
 
# Return the version number of this application.
4
# The application includes everything that is not included in the module this file is published for: custom functions, layouts, records, etc.
 
# The application includes everything that is not included in the module this file is published for: custom functions, layouts, records, etc.
5
#
 
#
6
# RETURNS:
 
# RETURNS:
7
# version string portion of the script name
 
# version string portion of the script name
8
#
 
#
9
# NOTES:
 
# NOTES:
10
# http://filemakerstandards.org/display/bp/Default+scripts
 
# http://filemakerstandards.org/display/bp/Default+scripts
11
# This guideline was heavily influenced by http://semver.org/spec/v2.0.0-rc.1.html
 
# This guideline was heavily influenced by http://semver.org/spec/v2.0.0-rc.1.html
12
# Changelog: Summary is formatted with markdown: http://daringfireball.net/projects/markdown/ - use different header 'tag' (#'s) depending on the version being incremented Major: H1 Minor: H2 Patch: H3
 
# Changelog: Summary is formatted with markdown: http://daringfireball.net/projects/markdown/ - use different header 'tag' (#'s) depending on the version being incremented Major: H1 Minor: H2 Patch: H3
13
# ###############################################################################
 
# ###############################################################################
14
Set Variable[ $scriptResult; Value: Let( [anon0 = Get( ScriptName ); anon1 = Left( Filter( anon0; "0123456789" ); 1 ); anon2 = Position( anon0; anon1; 1; 1 )]; Right( anon0; Length( anon0 ) - anon2 + 1 ) ) ]
 
Set Variable[ $scriptResult; Value: Let( [anon0 = Get( ScriptName ); anon1 = Left( Filter( anon0; "0123456789" ); 1 ); anon2 = Position( anon0; anon1; 1; 1 )]; Right( anon0; Length( anon0 ) - anon2 + 1 ) ) ]
15
Exit Script[ Result: $scriptResult ]
 
Exit Script[ Result: $scriptResult ]
16
#
 
#
17
# MAJOR.MINOR.PATCH{-PRERELEASE}{+}
 
# MAJOR.MINOR.PATCH{-PRERELEASE}{+}
18
# MAJOR: Arbitrarily defined by the developer, but must introduce significant change to either the feature set, or the internal method of processing.
 
# MAJOR: Arbitrarily defined by the developer, but must introduce significant change to either the feature set, or the internal method of processing.
19
# MINOR: New features. Should be incremented whenever a new feature is added.
 
# MINOR: New features. Should be incremented whenever a new feature is added.
20
# PATCH: Bug fixes. Should not introduce new features (unless the lack of that feature can be considered a bug).
 
# PATCH: Bug fixes. Should not introduce new features (unless the lack of that feature can be considered a bug).
21
# {-PRERELEASE} OPTIONAL A pre-release version MAY be denoted by appending a dash and a series of dot separated identifiers immediately following the patch version. Identifiers MUST be comprised of only ASCII alphanumerics and dash [0-9A-Za-z-]. Pre-release versions satisfy but have a lower precedence than the associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92. This value can be compaired as text in FileMaker, and the following will be true: "alpha" < "beta" and "alpha" < "rc" and "beta" < "rc".
 
# {-PRERELEASE} OPTIONAL A pre-release version MAY be denoted by appending a dash and a series of dot separated identifiers immediately following the patch version. Identifiers MUST be comprised of only ASCII alphanumerics and dash [0-9A-Za-z-]. Pre-release versions satisfy but have a lower precedence than the associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92. This value can be compaired as text in FileMaker, and the following will be true: "alpha" < "beta" and "alpha" < "rc" and "beta" < "rc".
22
# {+} OPTIONAL If the file has been modified since the version was last incremented, and the version does not need to be incremented yet (still under development), append the version string with a +.
 
# {+} OPTIONAL If the file has been modified since the version was last incremented, and the version does not need to be incremented yet (still under development), append the version string with a +.
23
#
 
#
24
# These guidelines should be followed:
 
# These guidelines should be followed:
25
# Use decimal separated text to store the version.
 
# Use decimal separated text to store the version.
26
# When evaluating the version, MUST NOT convert the entire text to a number. Each decimal separated section must be evaluated individually, and in order. Here is a possible method of doing so: Let ( [ ver = "1.2.21" ; // extract pre-release version string ver = Substitute ( ver ; "-" ; ¶ ) ; preRelease = GetValue ( ver ; 2 ) ; // extract normal version string ver = GetValue ( ver ; 1 ) ; ver = Substitute ( ver ; "." ; ¶ ) ; major = GetAsNumber ( GetValue ( ver ; 1 ) ) ; minor = GetAsNumber ( GetValue ( ver ; 2 ) ) ; patch = GetAsNumber ( GetValue ( ver ; 3 ) ) ] ; // evaluate version Case ( major = 0 ; "initial development" ; major = 1 ; "first public release" ) )
 
# When evaluating the version, MUST NOT convert the entire text to a number. Each decimal separated section must be evaluated individually, and in order. Here is a possible method of doing so: Let ( [ ver = "1.2.21" ; // extract pre-release version string ver = Substitute ( ver ; "-" ; ¶ ) ; preRelease = GetValue ( ver ; 2 ) ; // extract normal version string ver = GetValue ( ver ; 1 ) ; ver = Substitute ( ver ; "." ; ¶ ) ; major = GetAsNumber ( GetValue ( ver ; 1 ) ) ; minor = GetAsNumber ( GetValue ( ver ; 2 ) ) ; patch = GetAsNumber ( GetValue ( ver ; 3 ) ) ] ; // evaluate version Case ( major = 0 ; "initial development" ; major = 1 ; "first public release" ) )
27
# Summarize the changes of each version in a single comment step below. This should be a brief overview of the changes, whereas the Changelog: Detailed script contains the detailed daily changes.
 
# Summarize the changes of each version in a single comment step below. This should be a brief overview of the changes, whereas the Changelog: Detailed script contains the detailed daily changes.
28
#
 
#
29
#
 
#
30
# ==============================================================================
 
# ==============================================================================
31
# CHANGELOG: SUMMARY
 
# CHANGELOG: SUMMARY
32
# ==============================================================================
 
# ==============================================================================
33
#
 
#
34
 
 
# ### 1.0.1 ### - unit tests for FM-JSON: - "text miss-interpreted as a date" unit test now produces expected result - add unit tests for "quoted number treated as list" bug - add misc. unit tests - add unit tests with large chunks of data to better represent real-world data - update custom functions to current #Parameters module version 1.1.3: - # - #List
35
# # 1.0.0 # - the first release of this file did not include a separate version script for the application. This version script was created with JSON: Version 1.0.1. - updated custom functions: # #GetNameList #List - add unit tests for JSON-FM: - Object with returns - Array with returns - unit tests for FM-JSON: - modify: Escape characters pt 2: returns/line endings - add: Escape characters pt 4: returns/line endings in object - scripts - added - JSON-FM: Go To - FM-JSON: Go To - deleted - Toggle section - modified - FM-JSON: Parse All Found - FM-JSON: Parse letNotation text { skipRefresh } - FM-JSON: Parse letNotation expression { skipRefresh } - update navigation button in header
 
# # 1.0.0 # - the first release of this file did not include a separate version script for the application. This version script was created with JSON: Version 1.0.1. - updated custom functions: # #GetNameList #List - add unit tests for JSON-FM: - Object with returns - Array with returns - unit tests for FM-JSON: - modify: Escape characters pt 2: returns/line endings - add: Escape characters pt 4: returns/line endings in object - scripts - added - JSON-FM: Go To - FM-JSON: Go To - deleted - Toggle section - modified - FM-JSON: Parse All Found - FM-JSON: Parse letNotation text { skipRefresh } - FM-JSON: Parse letNotation expression { skipRefresh } - update navigation button in header
36
#
 
#
End of Report
 
Legend:
--
Element does not exist in this file.
Please see FMDiff.com for further details.
--------------------------------------------------------------------------------