Boxlang 1.x Stable Released
BoxLang : A Modern Dynamic JVM Language
LogoLogo
APIDocsDownloadTrySourceSupport
  • Introduction
    • Contributing Guide
    • Release History
      • 1.2.0
      • 1.1.0
      • 1.0.1
      • 1.0.0
      • RC Stage
        • 1.0.0-RC.1
        • 1.0.0-RC.2
        • 1.0.0-RC.3
      • Beta Stage
        • 1.0.0-Beta27
        • 1.0.0-Beta26
        • 1.0.0-Beta25
        • 1.0.0-Beta24
        • 1.0.0-Beta23
        • 1.0.0-Beta22
        • 1.0.0-Beta21
        • 1.0.0-Beta20
        • 1.0.0-Beta19
        • 1.0.0-Beta18
        • 1.0.0-Beta17
        • 1.0.0-Beta16
        • 1.0.0-Beta15
        • 1.0.0-Beta14
        • 1.0.0-Beta13
        • 1.0.0-Beta12
        • 1.0.0-Beta11
        • 1.0.0-Beta10
        • 1.0.0-Beta9
        • 1.0.0-Beta8
        • 1.0.0-Beta7
        • 1.0.0-Beta6
        • 1.0.0-Beta5
        • 1.0.0-Beta 4
        • 1.0.0-Beta3
        • 1.0.0-Beta2
    • About This Book
      • Authors
  • Getting Started
    • Overview
      • Multi-Runtime
      • Instructions & Interpreters
      • CommandBox CLI
      • Quick Syntax Guide
        • Differences From CFML
      • Frequently Asked Questions
      • Running ColdFusion/CFML Apps
        • Migrating from Adobe ColdFusion
        • Migrating From Lucee CFML
    • Installation
      • BoxLang Quick Installer
      • BoxLang Version Manager (BVM)
      • Modules
    • Running BoxLang
      • AWS Lambda
      • CommandBox
      • Chromebooks
      • CLI Scripting
      • Docker
      • GitHub Actions
      • JSR-223 Scripting
      • MiniServer
      • Try BoxLang!
    • BoxLang Cloud Servers
      • Microsoft Azure
      • Amazon Web Services
    • IDE & Tooling
      • BoxLang Debugger
        • MiniServer Debugging
        • CommandBox Debugging
      • BoxLang Compiler
      • CFML Feature Audit
      • CFML to BoxLang Transpiler
    • Runtime Configuration
      • Directives
      • Caches
      • Datasources
      • Experimental
      • Executors
      • Logging
      • Maven Integration
      • Modules
      • Security
  • BoxLang Language
    • Program Structure
    • Syntax & Semantics
      • Comments
      • Variables
      • Variable Scopes
      • Operators
      • Null & Nothingness
      • Strings
      • Numbers
      • Dates & Times
      • JSON
      • Arrays
      • Structures
      • Queries
      • Datasources
      • Conditionals
      • Attempts
      • Data Navigators
      • Exception Management
      • Code Locking
      • Closures => Context Aware
      • Lambdas -> Pure Functions
      • Includes
      • Threading
    • Classes & O.O.
      • Properties
      • Functions
      • Static Constructs
      • Final Constructs
      • Abstract Constructs
      • Interfaces
    • Reference
      • API Docs
      • Lexical Elements
        • Scopes and Constants
        • Keywords
        • Operators
        • Literals
        • Comments
        • Tokens
        • Semicolons
        • Identifiers
        • Packages and Imports
        • Java Interoperability
        • Errors
      • Types
        • array
        • class
        • datetime
        • file
        • numeric
        • query
        • stream
        • string
        • struct
        • xml
      • Built-in Functions
        • array
          • ArrayAppend
          • ArrayAvg
          • ArrayClear
          • ArrayContains
          • ArrayContainsNoCase
          • ArrayDelete
          • ArrayDeleteAt
          • ArrayDeleteNoCase
          • ArrayEach
          • ArrayEvery
          • ArrayFilter
          • ArrayFind
          • ArrayFindAll
          • ArrayFindAllNoCase
          • ArrayFindNoCase
          • ArrayFirst
          • ArrayGetMetadata
          • ArrayIndexExists
          • ArrayInsertAt
          • ArrayIsDefined
          • ArrayLast
          • ArrayMap
          • ArrayMax
          • ArrayMedian
          • ArrayMerge
          • ArrayMid
          • ArrayMin
          • ArrayNew
          • ArrayPop
          • ArrayPrepend
          • ArrayPush
          • ArrayRange
          • ArrayReduce
          • ArrayReduceRight
          • ArrayResize
          • ArrayReverse
          • ArraySet
          • ArrayShift
          • ArraySlice
          • ArraySome
          • ArraySort
          • ArraySplice
          • ArraySum
          • ArraySwap
          • ArrayToList
          • ArrayToStruct
          • ArrayUnshift
        • async
          • ExecutorGet
          • ExecutorHas
          • ExecutorList
          • ExecutorNew
          • ExecutorShutdown
          • ExecutorStatus
          • FutureNew
          • IsInThread
          • isThreadAlive
          • IsThreadInterrupted
          • RunAsync
          • ThreadInterrupt
          • ThreadJoin
          • ThreadNew
          • ThreadTerminate
        • binary
          • BinaryDecode
          • BinaryEncode
          • BitAnd
          • BitMaskClear
          • BitMaskRead
          • BitMaskSet
          • BitNot
          • BitOr
          • bitShln
          • bitShrn
          • BitXor
        • cache
          • Cache
          • CacheFilter
          • CacheNames
          • CacheProviders
          • CacheService
        • cli
          • CLIClear
          • CLIExit
          • CLIGetArgs
          • CLIRead
        • conversion
          • DataNavigate
          • JSONDeserialize
          • JSONPrettify
          • JSONSerialize
          • LSParseNumber
          • ParseNumber
          • ToBase64
          • ToBinary
          • ToModifiable
          • ToNumeric
          • ToScript
          • ToString
          • ToUnmodifiable
        • decision
          • ArrayIsEmpty
          • arrayIsEmpty
          • Attempt
          • IsArray
          • IsBinary
          • IsBoolean
          • IsClosure
          • IsCustomFunction
          • IsDate
          • IsDateObject
          • IsDebugMode
          • IsDefined
          • IsEmpty
          • IsFileObject
          • IsIPv6
          • IsJSON
          • IsLeapYear
          • IsLocalHost
          • IsNull
          • IsNumeric
          • IsNumericDate
          • IsObject
          • IsQuery
          • IsSimpleValue
          • IsStruct
          • IsValid
          • IsXML
          • IsXmlAttribute
          • IsXMLDoc
          • IsXMLElem
          • IsXMLNode
          • IsXMLRoot
          • LSIsNumeric
          • structIsEmpty
        • encryption
          • Decrypt
          • DecryptBinary
          • Encrypt
          • EncryptBinary
          • GeneratePBKDFKey
          • GenerateSecretKey
          • Hash
          • Hash40
          • Hmac
        • format
          • BooleanFormat
          • DecimalFormat
          • LSNumberFormat
          • NumberFormat
        • i18n
          • ClearLocale
          • CurrencyFormat
          • GetLocale
          • GetLocaleDisplayName
          • GetLocaleInfo
          • IsCurrency
          • LSCurrencyFormat
          • LSIsCurrency
          • LSParseCurrency
          • ParseCurrency
          • SetLocale
        • io
          • ContractPath
          • CreateTempDirectory
          • CreateTempFile
          • DirectoryCopy
          • DirectoryCreate
          • DirectoryDelete
          • DirectoryExists
          • DirectoryList
          • DirectoryMove
          • DirectoryRename
          • ExpandPath
          • FileAppend
          • FileClose
          • FileCopy
          • FileDelete
          • FileExists
          • FileGetMimeType
          • FileInfo
          • FileIsEOF
          • FileMove
          • FileOpen
          • FileRead
          • FileReadBinary
          • FileReadLine
          • FileSeek
          • FileSetAccessMode
          • FileSetAttribute
          • FileSetLastModified
          • FileSkipBytes
          • FileWrite
          • FileWriteLine
          • GetCanonicalPath
          • GetDirectoryFromPath
          • GetFileInfo
          • getTempFile
        • java
          • CreateDynamicProxy
        • jdbc
          • IsInTransaction
          • IsWithinTransaction
          • PreserveSingleQuotes
          • QueryExecute
          • TransactionCommit
          • TransactionRollback
          • TransactionSetSavepoint
        • list
          • GetToken
          • ListAppend
          • ListAvg
          • ListChangeDelims
          • ListCompact
          • ListContains
          • ListContainsNoCase
          • ListDeleteAt
          • ListEach
          • ListEvery
          • ListFilter
          • ListFind
          • ListFindNoCase
          • ListFirst
          • ListGetAt
          • ListIndexExists
          • ListInsertAt
          • ListItemTrim
          • ListLast
          • ListLen
          • ListMap
          • ListPrepend
          • ListQualify
          • ListReduceRight
          • ListRemoveDuplicates
          • ListRest
          • ListSetAt
          • ListSome
          • ListSort
          • ListToArray
          • ListTrim
          • ListValueCount
          • ListValueCountNoCase
        • math
          • Abs
          • Acos
          • Asin
          • Atn
          • Ceiling
          • Cos
          • DecrementValue
          • Exp
          • Fix
          • Floor
          • FormatBaseN
          • IncrementValue
          • InputBaseN
          • Int
          • Log
          • Log10
          • Max
          • Min
          • Pi
          • PrecisionEvaluate
          • Rand
          • Randomize
          • RandRange
          • Round
          • Sgn
          • Sin
          • Sqr
          • Tan
        • query
          • QueryAddColumn
          • QueryAddRow
          • QueryAppend
          • QueryClear
          • QueryColumnArray
          • QueryColumnCount
          • QueryColumnData
          • QueryColumnExists
          • QueryColumnList
          • QueryCurrentRow
          • QueryDeleteColumn
          • QueryDeleteRow
          • QueryEach
          • QueryEvery
          • QueryFilter
          • QueryGetCell
          • QueryGetResult
          • QueryInsertAt
          • QueryKeyExists
          • QueryMap
          • QueryNew
          • QueryPrepend
          • QueryRecordCount
          • QueryReduce
          • QueryRegisterFunction
          • QueryReverse
          • QueryRowData
          • QueryRowSwap
          • QuerySetCell
          • QuerySetRow
          • QuerySlice
          • QuerySome
          • QuerySort
        • runtime
          • BoxLangBIFProxy
        • scheduler
          • SchedulerGet
          • SchedulerGetAll
          • SchedulerList
          • SchedulerRestart
          • SchedulerShutdown
          • SchedulerStart
          • SchedulerStats
        • string
          • Ascii
          • CamelCase
          • Char
          • CharsetDecode
          • CharsetEncode
          • Compare
          • CompareNoCase
          • Find
          • FindNoCase
          • FindOneOf
          • Insert
          • JSStringFormat
          • KebabCase
          • LCase
          • Left
          • ListReduce
          • LJustify
          • LTrim
          • Mid
          • ParagraphFormat
          • PascalCase
          • QueryStringToStruct
          • ReEscape
          • ReFind
          • reFindNoCase
          • ReMatch
          • reMatchNoCase
          • RemoveChars
          • RepeatString
          • Replace
          • ReplaceList
          • ReplaceListNoCase
          • ReplaceNoCase
          • ReReplace
          • reReplaceNoCase
          • Reverse
          • Right
          • RJustify
          • RTrim
          • Slugify
          • SnakeCase
          • SpanExcluding
          • SpanIncluding
          • SQLPrettify
          • StringBind
          • StringEach
          • StringEvery
          • StringFilter
          • StringMap
          • StringReduce
          • StringReduceRight
          • StringSome
          • StringSort
          • StripCR
          • Trim
          • TrueFalseFormat
          • UCase
          • UCFirst
          • Val
          • Wrap
          • YesNoFormat
        • struct
          • StructAppend
          • StructClear
          • StructCopy
          • StructDelete
          • StructEach
          • StructEquals
          • StructEvery
          • StructFilter
          • StructFind
          • StructFindKey
          • StructFindValue
          • StructGet
          • StructGetMetadata
          • StructInsert
          • StructIsCaseSensitive
          • StructIsOrdered
          • StructKeyArray
          • StructKeyExists
          • StructKeyList
          • StructKeyTranslate
          • StructMap
          • StructNew
          • StructReduce
          • StructSome
          • StructSort
          • StructToQueryString
          • StructToSorted
          • StructUpdate
          • StructValueArray
        • system
          • ApplicationRestart
          • ApplicationStartTime
          • ApplicationStop
          • BoxAnnounce
          • BoxAnnounceAsync
          • BoxModuleReload
          • BoxRegisterInterceptionPoints
          • BoxRegisterInterceptor
          • BoxRegisterRequestInterceptor
          • BoxUnregisterInterceptor
          • BoxUnregisterRequestInterceptor
          • CallStackGet
          • CreateGUID
          • CreateObject
          • CreateUUID
          • DE
          • DebugBoxContexts
          • Dump
          • Duplicate
          • echo
          • EncodeForHTML
          • GetApplicationMetadata
          • GetBaseTagData
          • GetBaseTagList
          • GetBaseTemplatePath
          • GetBoxContext
          • GetBoxRuntime
          • GetBoxVersionInfo
          • GetClassMetadata
          • GetComponentList
          • GetContextRoot
          • GetCurrentTemplatePath
          • GetFileFromPath
          • GetFunctionCalledName
          • GetFunctionList
          • GetModuleInfo
          • GetModuleList
          • GetRequestClassLoader
          • GetSemver
          • GetSystemSetting
          • GetTempDirectory
          • GetTickCount
          • htmlEditFormat
          • IIF
          • Invoke
          • IsInstanceOf
          • JavaCast
          • ObjectDeserialize
          • ObjectSerialize
          • PagePoolClear
          • Print
          • Println
          • RunThreadInContext
          • SessionInvalidate
          • SessionRotate
          • SessionStartTime
          • Sleep
          • SystemCacheClear
          • SystemExecute
          • SystemOutput
          • Throw
          • Trace
          • URLDecode
          • URLEncodedFormat
          • writeDump
          • WriteLog
          • WriteOutput
        • temporal
          • ClearTimezone
          • CreateDate
          • CreateDateTime
          • CreateODBCDate
          • CreateODBCDateTime
          • CreateODBCTime
          • CreateTime
          • CreateTimeSpan
          • DateAdd
          • DateCompare
          • DateConvert
          • DateDiff
          • DateFormat
          • DatePart
          • DateTimeFormat
          • Day
          • DayOfWeek
          • DayOfWeekAsString
          • DayOfWeekShortAsString
          • DayOfYear
          • DaysInMonth
          • DaysInYear
          • FirstDayOfMonth
          • GetNumericDate
          • GetTime
          • GetTimezone
          • GetTimezoneInfo
          • Hour
          • Millisecond
          • Minute
          • Month
          • MonthAsString
          • MonthShortAsString
          • Nanosecond
          • Now
          • Offset
          • ParseDateTime
          • Quarter
          • Second
          • SetTimezone
          • TimeFormat
          • Week
          • Year
        • type
          • ArrayLen
          • GetMetaData
          • Len
          • NullValue
          • StringLen
          • StructCount
        • xml
          • XMLChildPos
          • XMLElemNew
          • XMLFormat
          • XMLGetNodeType
          • XMLNew
          • XMLParse
          • XMLSearch
          • XMLTransform
          • XMLValidate
        • zip
          • Compress
          • Extract
          • IsZipFile
      • Components
        • async
          • Thread
        • cache
          • Cache
        • debug
          • Timer
        • io
          • Directory
          • File
        • jdbc
          • ProcParam
          • StoredProc
          • DBInfo
          • ProcResult
          • Query
          • QueryParam
          • Transaction
        • net
          • HTTPParam
          • HTTP
        • system
          • Throw
          • InvokeArgument
          • Application
          • Invoke
          • Abort
          • Include
          • Component
          • Execute
          • Flush
          • SaveContent
          • Output
          • Log
          • Sleep
          • Setting
          • Param
          • Lock
          • Associate
          • Silent
          • ProcessingDirective
          • Trace
          • Exit
          • Dump
          • Loop
        • xml
          • XML
        • zip
          • Zip
      • Exceptions
  • BoxLang Framework
    • Application.bx
    • Asynchronous Programming
    • Caching
      • Cache Service
      • BoxCache Provider
      • Custom Cache Providers
      • Custom Object Stores
      • Custom Eviction Policies
    • File Handling
    • Interceptors
      • Core Interception Points
        • Application Events
        • Cache Service Events
        • Cache Provider Events
        • Cache Object Store Events
        • Datasource Service Events
        • Dump Events
        • Dynamic Object Events
        • Function Invocations
        • HTTP Events
        • Life-cycle Events
        • Logging Events
        • Module Events
        • Module Service Events
        • Object Marshalling Events
        • Query Invocations
        • Runtime Events
        • Request Context Events
        • Scheduler Events
        • Scheduler Service Events
        • Template Invocations
        • Transaction Events
      • Request Interception Points
    • HTTP/S Calls
    • Java Interop
    • JDBC Transactions
    • Modules
      • AI
      • Compat CFML
        • Reference
          • Types
            • array
            • datetime
            • numeric
            • string
            • struct
          • Built-in Functions
            • cache
              • CacheCount
              • CacheGetAsAttempt
              • CacheRegionRemove
              • CacheRemoveAll
              • CachePut
              • CacheRegionExists
              • CacheGetSession
              • CacheGetEngineProperties
              • CacheGet
              • CacheGetDefaultCacheName
              • CacheGetProperties
              • CacheSetProperties
              • CacheGetAllIds
              • CacheIdExists
              • cacheKeyExists
              • CacheRemove
              • cacheDelete
              • CacheGetAll
              • CacheGetMetadata
              • CacheGetOrFail
              • CacheClear
              • CacheRegionNew
            • conversion
              • JSONDeserialize
            • encryption
              • Hash
              • Hash40
            • format
              • HTMLCodeFormat
              • DollarFormat
            • struct
              • DeleteClientVariable
            • system
              • Throw
              • ObjectSave
              • GetFunctionData
              • GetComponentMetadata
              • GetVariable
              • GetTagData
              • GetClientVariablesList
              • GetContextRoot
              • ObjectLoad
              • SetVariable
            • temporal
              • LSWeek
              • LSDayOfWeek
              • LSIsDate
              • DateCompare
              • GetHTTPTimestring
              • LSDateTimeFormat
              • LSDateFormat
              • LSTimeFormat
              • DayOfWeekAsString
              • DayOfWeekShortAsString
              • MonthAsString
              • MonthShortAsString
              • ToLegacyDate
              • createDate
              • LSParseDateTime
              • DateTimeFormat
              • DateFormat
              • TimeFormat
            • type
              • GetMetaData
          • Components
            • net
              • HTTP
      • CSRF
      • ESAPI
      • Evaluating Code
      • FTP
      • Image Manipulation
      • INI Files
      • JDBC
      • Jython
      • Mail
      • Markdown
      • ORM
      • OSHI - Operating System + Hardware
      • Password Encryption
      • PDF
      • Redis
      • UI Forms
      • WDDX
      • Web Support
      • Yaml
  • Extra Credit
    • MVC
    • Dependency Injection
Powered by GitBook
LogoLogo

Social Media

  • X
  • FaceBook
  • LinkedIn
  • YouTube

Bug Tracking

  • Runtimes
  • IDE
  • Modules

Support

  • Professional
  • Community
  • Slack

Copyright & Register Trademark by Ortus Solutions, Corp

On this page
  • Overview
  • Getting Started
  • Creating a Data Navigator
  • Basic Navigation
  • Navigation Methods
  • Data Extraction Methods
  • Conditional Processing
  • Practical Examples
  • Error Handling and Validation
  • Advanced Patterns
  • Best Practices
  • Conclusion

Was this helpful?

Edit on GitHub
Export as PDF
  1. BoxLang Language
  2. Syntax & Semantics

Data Navigators

Data Navigators provide a fluent, safe way to navigate and extract data from complex data structures in BoxLang

Data Navigators are a powerful BoxLang feature that provides a fluent, chainable interface for safely navigating and extracting data from complex data structures. Whether you're working with JSON files, API responses, configuration data, or nested structures, Data Navigators eliminate the need for verbose null checking and provide elegant error handling.

Overview

Data Navigators solve common problems when working with complex data:

  • Safe Navigation: No more "key doesn't exist" errors when traversing nested structures

  • Fluent Interface: Chainable methods that read like natural language

  • Type Safety: Built-in type casting with sensible defaults

  • Multiple Data Sources: Works with JSON strings, files, structures, maps, and more

  • Flexible Extraction: Get values with defaults, throw on missing data, or check existence

Getting Started

Creating a Data Navigator

Use the dataNavigate() BIF to create a navigator from various data sources:

// From a structure
config = {
    "app": {
        "name": "MyApp",
        "version": "1.0.0",
        "database": {
            "host": "localhost",
            "port": 5432,
            "ssl": true
        }
    }
}
nav = dataNavigate( config )

// From a JSON string
jsonData = '{"users": [{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]}'
nav = dataNavigate( jsonData )

// From a JSON file
nav = dataNavigate( "/path/to/config.json" )

// From a Java Map
javaMap = new java.util.HashMap()
nav = dataNavigate( javaMap )

Basic Navigation

Navigate through nested structures using the fluent interface:

// Setup test data
appConfig = {
    "application": {
        "name": "BoxLang App",
        "version": "2.0.0",
        "features": {
            "caching": true,
            "logging": {
                "level": "INFO",
                "appenders": [ "console", "file" ]
            }
        }
    }
}

nav = dataNavigate( appConfig )

// Navigate to a specific section
loggingNav = nav.from( "application", "features", "logging" )

// Get values with defaults
logLevel = loggingNav.getAsString( "level", "DEBUG" )
println( "Log Level: " & logLevel ) // "INFO"

// Check if values exist
if ( loggingNav.has( "appenders" ) ) {
    appenders = loggingNav.getAsArray( "appenders" )
    println( "Appenders: " & appenders.toList() )
}

Navigation Methods

Navigate to Segments

// Navigate to nested sections
userNav = dataNavigate( userData ).from( "profile", "settings" )
dbNav = dataNavigate( config ).from( "database" )

// Multiple level navigation
deepNav = dataNavigate( complexData )
    .from( "api", "v1" )
    .from( "endpoints", "users" )

Check Existence

nav = dataNavigate( config )

// Check if keys exist
hasDatabase = nav.has( "database" )
hasSSLConfig = nav.has( "database", "ssl", "enabled" )

// Check current segment
userNav = nav.from( "users" )
if ( userNav.isPresent() ) {
    println( "Users section exists" )
}

if ( userNav.isEmpty() ) {
    println( "Users section is empty" )
}

Data Extraction Methods

Basic Retrieval

nav = dataNavigate( appConfig )

// Get raw values
appName = nav.get( "application", "name" )
version = nav.get( "application", "version" )

// Get with defaults
timeout = nav.get( "application", "timeout", 30 )
retries = nav.get( "application", "retries", 3 )

// Throw if missing (for required values)
apiKey = nav.getOrThrow( "application", "apiKey" )

Basic Retrieval

nav = dataNavigate( serverConfig )

// BoxLang is dynamic - get() handles all types automatically
serverName = nav.get( "server", "name", "default-server" )
port = nav.get( "server", "port", 8080 )
sslEnabled = nav.get( "server", "ssl", false )
timeout = nav.get( "server", "timeout", 5000 )
lastUpdated = nav.get( "server", "lastUpdated" )

// Complex types work too
dbConfig = nav.get( "database" )
serverList = nav.get( "servers" )

Typed Retrievals

For cases where you need explicit type conversion, BoxLang provides typed methods:

// Only use these when you need explicit type conversion
port = nav.getAsInteger( "server", "port", 8080 )
timeout = nav.getAsLong( "server", "timeout", 5000 )
loadFactor = nav.getAsDouble( "server", "loadFactor", 0.75 )
sslEnabled = nav.getAsBoolean( "server", "ssl", false )
lastUpdated = nav.getAsDate( "server", "lastUpdated" )
dbConfig = nav.getAsStruct( "database" )
serverList = nav.getAsArray( "servers" )

Conditional Processing

Execute Code Based on Presence

nav = dataNavigate( userProfile )

// Execute if key exists
nav.ifPresent( "email", email -> {
    println( "User email: " & email )
    sendWelcomeEmail( email )
} )

// Execute with fallback
nav.ifPresentOrElse( 
    "phone",
    phone -> {
        println( "Calling: " & phone )
        makePhoneCall( phone )
    },
    () -> {
        println( "No phone number available" )
        sendEmailInstead()
    }
)

Practical Examples

Configuration Management

// Load application configuration
function loadAppConfig( configPath ) {
    var nav = dataNavigate( configPath )
    
    return {
        "appName": nav.get( "app", "name", "Unknown App" ),
        "version": nav.get( "app", "version", "1.0.0" ),
        "debug": nav.get( "app", "debug", false ),
        "database": {
            "host": nav.get( "database", "host", "localhost" ),
            "port": nav.get( "database", "port", 5432 ),
            "ssl": nav.get( "database", "ssl", true )
        },
        "cache": {
            "enabled": nav.get( "cache", "enabled", true ),
            "provider": nav.get( "cache", "provider", "memory" ),
            "ttl": nav.get( "cache", "ttl", 3600 )
        }
    }
}

// Usage
appConfig = loadAppConfig( "/app/config.json" )
println( "Starting " & appConfig.appName & " v" & appConfig.version )

API Response Processing

// Process API response data
function processUserData( apiResponse ) {
    var nav = dataNavigate( apiResponse )
    var users = [ ]
    
    // Check if response is successful
    if ( nav.getAsBoolean( "success", false ) ) {
        // Navigate to user data
        var userNav = nav.from( "data", "users" )
        
        if ( userNav.isPresent() ) {
            var userArray = userNav.getAsArray( "items", [ ] )
            
            for ( var userData in userArray ) {
                var userDataNav = dataNavigate( userData )
                
                users.append( {
                    "id": userDataNav.get( "id" ),
                    "name": userDataNav.get( "profile", "fullName", "Unknown" ),
                    "email": userDataNav.get( "contact", "email" ),
                    "active": userDataNav.get( "status", "active", false ),
                    "lastLogin": userDataNav.get( "activity", "lastLogin" )
                } )
            }
        }
    }
    
    return users
}

// Usage with API response
apiResponse = '
{
    "success": true,
    "data": {
        "users": {
            "items": [
                {
                    "id": "123",
                    "profile": {"fullName": "Alice Johnson"},
                    "contact": {"email": "alice@example.com"},
                    "status": {"active": true},
                    "activity": {"lastLogin": "2024-01-15T10:30:00Z"}
                }
            ]
        }
    }
}
'

users = processUserData( apiResponse )

Feature Flag Management

// Feature flag configuration
function createFeatureManager( configData ) {
    var nav = dataNavigate( configData )
    
    return {
        "isEnabled": ( feature ) -> {
            return nav.get( "features", feature, "enabled", false )
        },
        
        "getConfig": ( feature ) -> {
            var featureNav = nav.from( "features", feature )
            if ( featureNav.isEmpty() ) {
                return { }
            }
            
            return {
                "enabled": featureNav.get( "enabled", false ),
                "rolloutPercent": featureNav.get( "rollout", 100 ),
                "environments": featureNav.get( "environments", [ ] ),
                "config": featureNav.get( "config", { } )
            }
        },
        
        "shouldShowForUser": ( feature, userID ) -> {
            var config = this.getConfig( feature )
            if ( !config.enabled ) return false
            
            // Simple hash-based rollout
            var userHash = hash( userID ).left( 2 ).parseInt( 16 )
            return ( userHash % 100 ) < config.rolloutPercent
        }
    }
}

// Usage
featureConfig = '
{
    "features": {
        "newDashboard": {
            "enabled": true,
            "rollout": 50,
            "environments": ["staging", "production"]
        },
        "betaFeature": {
            "enabled": false
        }
    }
}
'

features = createFeatureManager( featureConfig )

if ( features.isEnabled( "newDashboard" ) ) {
    println( "New dashboard is enabled" )
}

Database Configuration

// Multi-environment database configuration
function getDatabaseConfig( environment = "development" ) {
    var nav = dataNavigate( "/config/database.json" )
    var envNav = nav.from( "environments", environment )
    
    // Fallback to default if environment not found
    if ( envNav.isEmpty() ) {
        envNav = nav.from( "environments", "default" )
    }
    
    var config = {
        "driver": envNav.get( "driver", "mysql" ),
        "host": envNav.get( "host", "localhost" ),
        "port": envNav.get( "port", 3306 ),
        "database": envNav.get( "database", "myapp" ),
        "username": envNav.get( "username", "root" ),
        "password": envNav.get( "password", "" ),
        "ssl": envNav.get( "ssl", false ),
        "pooling": {
            "enabled": envNav.get( "pool", "enabled", true ),
            "maxConnections": envNav.get( "pool", "max", 10 ),
            "timeout": envNav.get( "pool", "timeout", 30 )
        }
    }
    
    // Apply global settings
    var globalNav = nav.from( "global" )
    if ( globalNav.isPresent() ) {
        config.charset = globalNav.get( "charset", "utf8" )
        config.timezone = globalNav.get( "timezone", "UTC" )
    }
    
    return config
}

// Usage
dbConfig = getDatabaseConfig( "production" )

Log Configuration Processing

// Parse logging configuration
function setupLogging( logConfigPath ) {
    var nav = dataNavigate( logConfigPath )
    var loggers = [ ]
    
    // Get global log level
    var globalLevel = nav.get( "logging", "level", "INFO" )
    
    // Process appenders
    var appendersNav = nav.from( "logging", "appenders" )
    if ( appendersNav.isPresent() ) {
        
        // Console appender
        appendersNav.ifPresent( "console", consoleConfig -> {
            var consoleNav = dataNavigate( consoleConfig )
            loggers.append( {
                "type": "console",
                "level": consoleNav.get( "level", globalLevel ),
                "pattern": consoleNav.get( "pattern", "%d{yyyy-MM-dd HH:mm:ss} - %m%n" ),
                "colored": consoleNav.get( "colored", true )
            } )
        } )
        
        // File appender
        appendersNav.ifPresent( "file", fileConfig -> {
            var fileNav = dataNavigate( fileConfig )
            loggers.append( {
                "type": "file",
                "level": fileNav.get( "level", globalLevel ),
                "path": fileNav.get( "path", "/logs/app.log" ),
                "maxSize": fileNav.get( "maxSize", "10MB" ),
                "maxFiles": fileNav.get( "maxFiles", 5 )
            } )
        } )
    }
    
    return loggers
}

Error Handling and Validation

Safe Navigation Patterns

// Safe navigation with validation
function getSecureConfig( configPath ) {
    try {
        var nav = dataNavigate( configPath )
        
        // Validate required sections exist
        if ( !nav.has( "security" ) ) {
            throw( type: "ConfigurationError", message: "Security configuration missing" )
        }
        
        var secNav = nav.from( "security" )
        
        return {
            "encryption": {
                "algorithm": secNav.getOrThrow( "encryption", "algorithm" ),
                "keyLength": secNav.get( "encryption", "keyLength", 256 ) // Keep as number
            },
            "authentication": {
                "provider": secNav.get( "auth", "provider", "local" ),
                "timeout": secNav.get( "auth", "timeout", 3600 ) // Keep as number
            }
        }
        
    } catch ( any e ) {
        writeLog( "Failed to load security config: " & e.message, "error" )
        return getDefaultSecurityConfig()
    }
}

function getDefaultSecurityConfig() {
    return {
        "encryption": {
            "algorithm": "AES",
            "keyLength": 256
        },
        "authentication": {
            "provider": "local",
            "timeout": 3600
        }
    }
}

Graceful Degradation

// Load configuration with graceful fallbacks
function loadConfigWithFallbacks( primaryPath, fallbackPath ) {
    var config = { }
    
    // Try primary configuration
    try {
        var primaryNav = dataNavigate( primaryPath )
        config = extractConfig( primaryNav )
        println( "Loaded primary configuration from: " & primaryPath )
    } catch ( any e ) {
        writeLog( "Primary config failed: " & e.message, "warn" )
        
        // Try fallback configuration
        try {
            var fallbackNav = dataNavigate( fallbackPath )
            config = extractConfig( fallbackNav )
            println( "Loaded fallback configuration from: " & fallbackPath )
        } catch ( any e2 ) {
            writeLog( "Fallback config failed: " & e2.message, "error" )
            config = getHardcodedDefaults()
            println( "Using hardcoded default configuration" )
        }
    }
    
    return config
}

function extractConfig( nav ) {
    return {
        "app": nav.get( "name", "DefaultApp" ),
        "port": nav.get( "server", "port", 8080 ),
        "debug": nav.get( "debug", false )
    }
}

Advanced Patterns

Configuration Inheritance

// Implement configuration inheritance
function buildInheritedConfig( environment ) {
    var nav = dataNavigate( "/config/app.json" )
    var config = { }
    
    // Start with base configuration
    var baseNav = nav.from( "base" )
    if ( baseNav.isPresent() ) {
        config = extractAllSettings( baseNav )
    }
    
    // Apply environment-specific overrides
    var envNav = nav.from( "environments", environment )
    if ( envNav.isPresent() ) {
        var envConfig = extractAllSettings( envNav )
        config = mergeConfigs( config, envConfig )
    }
    
    return config
}

function mergeConfigs( base, override ) {
    // Simple merge - in practice you'd want deep merging
    var merged = duplicate( base )
    for ( var key in override ) {
        merged[ key ] = override[ key ]
    }
    return merged
}

Dynamic Configuration Validation

// Validate configuration structure
function validateConfig( configData ) {
    var nav = dataNavigate( configData )
    var errors = [ ]
    
    // Required fields
    var required = [ 
        [ "app", "name" ],
        [ "app", "version" ],
        [ "database", "host" ]
    ]
    
    for ( var path in required ) {
        if ( !nav.has( path[ 1 ], path[ 2 ] ?: "" ) ) {
            errors.append( "Missing required field: " & path.toList( "." ) )
        }
    }
    
    // Type validations
    nav.ifPresent( "server", serverConfig -> {
        var serverNav = dataNavigate( serverConfig )
        var port = serverNav.get( "port" )
        
        if ( port != null && ( !isNumeric( port ) || port <= 0 || port > 65535 ) ) {
            errors.append( "Invalid port number: " & port )
        }
    } )
    
    return {
        "valid": errors.isEmpty(),
        "errors": errors
    }
}

Best Practices

1. Use Meaningful Defaults

// Provide sensible defaults for all configuration values - get() works dynamically
serverConfig = nav.get( "server", {
    "host": "localhost",
    "port": 8080,
    "ssl": false,
    "timeout": 30
} )

2. Validate Critical Configuration

// Always validate required configuration
apiKey = nav.getOrThrow( "api", "key" ) // Will throw if missing
dbHost = nav.getOrThrow( "database", "host" )

3. Leverage BoxLang's Dynamic Nature

// BoxLang handles all types automatically with get()
enabled = nav.get( "feature", "enabled", false )
maxRetries = nav.get( "http", "maxRetries", 3 )
serverName = nav.get( "server", "name", "default" )
config = nav.get( "database" ) // Works for complex types too

4. Handle Missing Sections Gracefully

// Check for section existence before processing
var cacheNav = nav.from( "cache" )
if ( cacheNav.isPresent() ) {
    // Configure caching
    setupCaching( cacheNav )
} else {
    // Use default caching or disable
    useDefaultCaching()
}

5. Log Configuration Issues

// Log when using fallbacks or defaults
nav.ifPresentOrElse(
    "timeout",
    timeout -> println( "Using configured timeout: " & timeout ),
    () -> println( "No timeout configured, using default: 30s" )
)

Conclusion

Data Navigators offer a robust and fluent way to work with complex data structures in BoxLang. They eliminate common errors, provide excellent defaults, and make configuration management both safe and readable.

Key benefits:

  • Safe Navigation: No more null pointer exceptions when traversing data

  • Type Safety: Built-in type conversion with sensible defaults

  • Fluent API: Chainable methods that read like natural language

  • Flexible Sources: Works with JSON files, strings, structures, and maps

  • Error Handling: Graceful fallbacks and validation capabilities

Whether you're processing API responses, managing application configuration, or working with complex data structures, Data Navigators make your code more robust and maintainable.

PreviousAttemptsNextException Management

Last updated 12 days ago

Was this helpful?