Skip to content

Instantly share code, notes, and snippets.

@steveAllen0112
Last active May 26, 2018 05:37
Show Gist options
  • Save steveAllen0112/181975d06c2977d343b70a233da76a88 to your computer and use it in GitHub Desktop.
Save steveAllen0112/181975d06c2977d343b70a233da76a88 to your computer and use it in GitHub Desktop.
JSONGetLayoutData ( fields ; config )
// JSONGetLayoutData ( fields ; config )
/****
* PURPOSE
* To grab all the fields off the current layout and process their values into a JSON object.
*
* PARAMETERS
* OPTIONAL : fields : List : Can be used instead of allowing the fields to be grabbed from the layout.
* OPTIONAL : config : JSONObject : Can be used to override the default handling configuration for the various use cases.
* ignore : JSONObject
* containers : JSONBoolean
* True (default) = pass over containers without handling them or including them.
* False = include Containers as Base64Encoded text.
* related : JSONBoolean
* True = pass over Related fields without handling them or including them.
* False (default) = include FIRST Related field value according to the handling instructions.
* repetitions : JSONBoolean
* True = pass over repeated fields (i.e. rep > 1) without handling them or including them.
* False (default) = include repeated fields according to the handling instructions.
* summaries : JSONBoolean
* True (default) = pass over Summary fields without handling them or including them.
* False = include Summary field values using GetSummary() .
* handle : JSONObject
* related : JSONString
* array (default) = include related data as elements in an array assigned to the related table name as the parent property.
* object = include related data as an object assigned to the related table name as the parent property,
* with each related field (no table name) as a property under the related table object.
* repetitions : JSONBoolean
* array (default) = include each repeated value as a value in an array assigned to the field name as the parent property.
* list = include all values from the repeated field as a return-delimited list.
*
* RETURNS
* OnSuccess : JSONObject : A JSON Object containing the data from the fields of the Current Record on the Current Layout, ignored or handled as specified.
* OnError : JSONString : Whatever String is returned from the various Evaluate() runs.
*
* AUTHOR
* Steve Allen <[email protected]>
* GitHub: steveAllen0112
*
* VERSION CONTROL
* Original: https://gist.github.com/steveAllen0112/181975d06c2977d343b70a233da76a88
*
* LICENSE
* MIT: https://choosealicense.com/licenses/mit/
*
***/
Let ([b=""
/* PARAMS (uncomment to test in Data Viewer) */
//; fields = ""
//; config = JSONSetElement ( ""
// /* ignore : True | False */
// ;[ "ignore.containers" ; True ; JSONBoolean ]
// ;[ "ignore.related" ; False ; JSONBoolean ]
// ;[ "ignore.summaries" ; False ; JSONBoolean ]
//
// /* handle : array | list */
// ;[ "handle.related" ; "array" ; JSONString ]
// ;[ "handle.repetitions" ; "array" ; JSONString ]
// )
/* CONFIG/SET UP DEFAULTS */
; alpha = "abcdefghijklmnopqrstuvwxyz"
; $json.types = JSONSetElement ( ""
;[ "text" ; "JSONString" ; JSONString ]
;[ "number" ; "JSONNumber" ; JSONString ]
;[ "date" ; "JSONString" ; JSONString ]
;[ "time" ; "JSONString" ; JSONString ]
;[ "timestamp" ; "JSONString" ; JSONString ]
;[ "container" ; "JSONString" ; JSONString ]
)
; $json.setLine = ";[ {{key}} ; {{value}} ; {{type}} ]"
; $file.name = Get ( FileName )
; $layout.name = Get ( LayoutName )
; $table.name = Get ( LayoutTableName )
; fields = Case ( IsEmpty ( fields ) ; FieldNames ( $file.name ; $layout.name ) ; fields )
/* ignore : True | False */
; $config.ignore.containers = True AND (NOT Exact ( Quote ( JSONGetElement ( config ; "ignore.containers" ) ) ; Quote ( 0 ) ))
; $config.ignore.repetitions = False OR JSONGetElement ( config ; "ignore.repetitions" )
; $config.ignore.summaries = True AND (NOT Exact ( Quote ( JSONGetElement ( config ; "ignore.summaries" ) ) ; Quote ( 0 ) ))
; $config.ignore.related = False or JSONGetElement ( config ; "ignore.related" )
/* handle : array | list */
; $config.handle.related = Filter ( Lower ( JSONGetElement ( config ; "handle.related" ) ) ; alpha )
; $config.handle.related = Case (0;0
; PatternCount ( "array|object" ; $config.handle.related )
; $config.handle.related
; "array"
)
; $config.handle.repetitions = Filter ( Lower ( JSONGetElement ( config ; "handle.repetitions" ) ) ; alpha )
; $config.handle.repetitions = Case (0;0
; PatternCount ( "array|list" ; $config.handle.repetitions )
; $config.handle.repetitions
; "array"
)
; $fields.added = ""
/* TEMPLATES */
/* *** TEMPLATE: HANDLE (BASE) *** */
; $template.handle.base = Substitute (
"
¶ Let([b=''
¶ ; json.key.table = ''
¶ ; json.key.field = $field.name
¶ {{template.handle.related}}
¶ {{template.handle.repetitions}}
¶ {{template.handle.summary}}
¶ {{template.handle.standard}}
¶ ; output = Substitute ( $json.setLine
¶ ;[ '{{key}}' ; Quote ( json.key.table & json.key.field ) ]
¶ ;[ '{{value}}' ; Case ( $json.type = 'JSONNumber' AND IsEmpty ( field.value ) ; Quote ( 'null' ) ; field.value ) ]
¶ ;[ '{{type}}' ; Case ( $json.type = 'JSONNumber' AND IsEmpty ( field.value ) ; Quote ( 'JSONNull' ) ; $json.type ) ]
¶ )
¶ ];
¶ output
¶ )
"
; "'" ; "\"" ) //end template.standard substitute
/* *** TEMPLATE: HANDLE STANDARD *** */
; $template.handle.standard = Substitute (
"
¶ ; field.value = GetField ( $field.name.fullyQualified )
¶ ; field.value = Case (0;0
¶ ; $field.dataType = 'text'
¶ ; Quote ( field.value )
¶ ; PatternCount ( 'number|date|time|timestamp' ; $field.dataType )
¶ ; GetAsNumber ( field.value )
¶ ; $field.dataType = 'container'
¶ ; Quote ( Base64Encode ( field.value ) )
¶ )
"
; "'" ; "\"" ) //end template.handle.standard substitute
/* *** /TEMPLATE: HANDLE STANDARD *** */
/* *** TEMPLATE: HANDLE SUMMARY *** */
; $template.handle.summary = Substitute (
"
¶ ; field.value = GetSummary( GetField ( $field.name.fullyQualified ) ; GetField ( $field.name.fullyQualified ) )
¶ ; field.value = Case (0;0
¶ ; $field.dataType = 'text'
¶ ; Quote ( field.value )
¶ ; PatternCount ( 'number|date|time|timestamp' ; $field.dataType )
¶ ; GetAsNumber ( field.value )
¶ ; ''
¶ )
"
; "'" ; "\"" ) //end template.handle.standard substitute
/* *** /TEMPLATE: HANDLE STANDARD *** */
/* *** TEMPLATE: HANDLE RELATED *** */
; $template.handle.related = Substitute (
"
¶ ; json.key.table = $field.table & Case ( $config.handle.related = 'array' ; '[0].' ; '.' )
¶ ; json.key.field = $field.name
¶ ; field.value = GetField ( $field.name.fullyQualified )
¶ ; field.value = Case (0;0
¶ ; $field.dataType = 'text'
¶ ; Quote ( field.value )
¶ ; PatternCount ( 'number|date|time|timestamp' ; $field.dataType )
¶ ; GetAsNumber ( field.value )
¶ ; Quote ( field.value )
¶ )
"
; "'" ; "\"" ) //end template.handle.related substitute
/* *** /TEMPLATE: HANDLE RELATED *** */
/* *** TEMPLATE: HANDLE REPEATING (BASE) *** */
; $template.handle.repetitions.base = Substitute (
"
¶ ; indices = JSONListKeys ( JSONSetElement ( '[]' ; $field.maxReps - 1 ; 'null' ; JSONRaw ) ; '' )
¶ ; first = '; GetRepetition ( {{field.name}} ; '
¶ ; last = ' + 1 )'
¶ ; middle = last & '\¶' & first
¶ ; str = Substitute ( 'List (\'\'\¶' & first & Substitute ( indices ; '\¶' ; middle ) & last & '\¶)' ; [ \"{{field.name}}\" ; $field.name ] )
¶ {{template.handle.repetitions.formatter}}
"
;[ "'" ; "\"" ]
) //end template.handle.repetitions base substitute
/* *** /TEMPLATE: HANDLE REPEATING (BASE) *** */
/* *** TEMPLATE: HANDLE REPEATING -- ARRAY *** */
; $template.handle.repetitions.formatter.array = Substitute (
"
¶ ; field.value = Quote ( Substitute ( '[\'{{values}}\']'
¶ ;[ '{{values}}' ; Evaluate ( str ) ]
¶ ;[ '?' ; 'null' ]
¶ ;[ '\¶' ; '\',\'' ]
¶ ) )
¶ ; $json.type = 'JSONArray'
"
; "'" ; "\"" ) //end template.handle.repetitions.formatter.array substitute
/* *** TEMPLATE: HANDLE REPEATING -- LIST *** */
; $template.handle.repetitions.formatter.list = Substitute (
"
¶ ; field.value = Quote ( Substitute ( '{{values}}'
¶ ;[ '{{values}}' ; Evaluate ( str ) ]
¶ ;[ '?' ; 'null' ]
¶ ) )
¶ ; $json.type = 'JSONString'
"
; "'" ; "\"" ) //end template.handle.repetitions.formatter.list substitute
/* *** /TEMPLATE: HANDLE REPEATING -- ARRAY *** */
/* *** TEMPLATE: BASE *** */
; $template.base =
"
¶ Case ( ValueCount ( FilterValues ( $fields.added ; '{{field.name}}' ) ) ; '' ; Let([b=''
¶ ; $field.name = '{{field.name}}'
¶ ; $fields.added = List ( $fields.added ; $field.name )
¶ ; field.isFullyQualified = PatternCount ( $field.name ; '::' ) > 0
¶ ; $field.name = Case ( field.isFullyQualified ; Substitute ( $field.name ; '::' ; '\¶' ) ; $field.name )
¶ ; $field.table = Case ( field.isFullyQualified ; GetValue ( $field.name ; 1 ) ; $table.name )
¶ ; $field.name = Case ( field.isFullyQualified ; GetValue ( $field.name ; 2 ) ; $field.name )
¶ ; $field.name.fullyQualified = $field.table & '::' & $field.name
¶ ; field.isRelated = field.isFullyQualified AND $field.table <> $table.name
¶ ; field.info = FieldType ( $file.name ; $field.name.fullyQualified )
¶ ; field.info = Substitute ( Lower ( field.info ) ; ' ' ; '\¶' )
¶ ; field.storage = GetValue ( field.info ; 1 )
¶ ; $field.dataType = GetValue ( field.info ; 2 )
¶ ; field.indexing = GetValue ( field.info ; 3 )
¶ ; $field.maxReps = GetValue ( field.info ; 4 )
¶ ; field.isRepeating = $field.maxReps > 1
¶ ; field.isSummary = PatternCount ( 'summary' ; field.storage )
¶ ; field.isContainer = $field.dataType = 'container'
¶ ; field.isGlobal = field.storage = 'global'
¶ ; use.related = field.isRelated
¶ ; use.summary = field.isSummary
¶ ; use.repeating = field.isRepeating
¶ ; use.standard = (not field.isSummary)
¶ AND (not field.isRepeating)
¶ AND (not field.isRelated)
¶ ; $json.type = JSONGetElement ( $json.types ; $field.dataType )
¶ ; handler.related = Case ( use.related ; $template.handle.related ; '' )
¶ ; handler.standard = Case ( use.standard ; $template.handle.standard ; '' )
¶ ; handler.summary = Case ( use.summary ; $template.handle.summary ; '' )
¶ ; handler.repetition = Case ( use.repeating ; Substitute ( $template.handle.repetitions.base
¶ ;[ '{{template.handle.repetitions.formatter}}' ; $template.handle.repetitions.formatter." & $config.handle.repetitions & " ]
¶ ) ; '' )
¶ ; handler.base = Substitute ( $template.handle.base
¶ ;[ '{{template.handle.related}}' ; handler.related ]
¶ ;[ '{{template.handle.repetitions}}' ; handler.repetition ]
¶ ;[ '{{template.handle.summary}}' ; handler.summary ]
¶ ;[ '{{template.handle.standard}}' ; handler.standard ]
¶ )
¶ ; baseCalcStr = Case (0;0
¶ ; field.isGlobal
¶ OR (field.isContainer AND $config.ignore.containers)
¶ OR (field.isSummary AND $config.ignore.summaries)
¶ OR (field.isRelated AND $config.ignore.related)
¶ OR (field.isRepeating AND $config.ignore.repetitions)
¶ ; ''
¶ ; handler.base
¶ )
¶ ; result = Case ( IsEmpty ( baseCalcStr ) ; '' ; Evaluate ( baseCalcStr ) )
¶ ];
¶ result
¶ )
¶ )
"
/* *** /TEMPLATE: BASE *** */
/* BUILD CALC STRINGS */
; first = "; Evaluate ( Substitute ( $template.base ; [ \"'\" ; \"\\\"\" ] ; [ \"{{field.name}}\" ; GetValue ( Substitute ( \""
; last = "\" ; \"[\" ; \"\¶\" ) ; 1 ) ] ) )"
; middle = List ( last ; first )
; allFieldsStr = List (""
; "List (\"\""
; first &
Substitute ( fields ; "¶" ; middle )
& last
; ")"
)
/* EVALUATE & ERROR TRAP */
; allFieldsJSON = Evaluate ( allFieldsStr )
; finalJSONStr = "JSONSetElement ( \"\"¶" & allFieldsJSON & "¶)"
; output = Evaluate ( finalJSONStr )
; errorCheck = Case ( output = "?" ; "ERROR" ; JSONFormatElements ( output ) )
];
/* RETURN */
errorCheck
)
/* CLEAN UP VARIABLES */
& Let ([b=""
; vars = "
json.types
json.setLine
file.name
layout.name
table.name
config.ignore.containers
config.ignore.repetitions
config.ignore.summaries
config.ignore.related
config.handle.related
config.handle.repetitions
fields.added
template.handle.base
template.handle.standard
template.handle.summary
template.handle.repetitions.base
template.handle.repetitions.formatter.array
template.handle.repetitions.formatter.list
json.type
template.base
field.name
field.name.fullyQualified
field.dataType
field.maxReps
"
];
Evaluate ( "Let ([b" & Substitute ( Left ( vars ; Length ( vars ) )
;[ " " ; "¶=\"\";$"]
) & "a" & Middle ( Random ; 3 ; 7 ) & "=\"\"];\"\")" )
)
@steveAllen0112
Copy link
Author

steveAllen0112 commented May 24, 2018

//TODO:

  • Implement Summary field handling
  • Implement Related Set grabbing (currently only grabs first one).
  • Implement handling repeating fields as return-delimited lists.
  • Implement edge case handling where no repetition set on the layout starts at 1 for the field.
  • Implement performance enhancement: only handle each field once. (keep track & ignore if already handled)
  • Implement performance measurements.
  • Build another version with separate functions for sub-tasks (not templates, but functions).
    • Do speed comparison
  • Do a version where the sub-functions are included in the parent function and identified by a Case statement and selected by parameter. (Because I can! lol )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment