Skip to content

Guide to Constructing and Reading JSON

JSONItem is the native class for dealing with JSON. Depending on how you use it, it treats your data as either a standard dictionary (key-value pairs) or a zero-indexed array.

Part 1: Building JSON

Building JSON from scratch means firing up a new JSONItem and throwing data at it. Don’t build JSON by stitching strings together. It breaks easily, you’ll mess up the escaping, and JSONItem makes it completely unnecessary.

The Basic Payload

When you just need to fire a flat object at a web service:

Var apiPayload As New JSONItem
apiPayload.Value("endpoint") = "/users/create"
apiPayload.Value("timestamp") = 1715423000
apiPayload.Value("forceSync") = True

// Get the string back
Var jsonString As String = apiPayload.ToString
// {"endpoint":"/users/create","timestamp":1715423000,"forceSync":true}

Making Arrays

If you’re making a list of tags or IDs, use the .Add method. The moment you call .Add, Xojo treats that JSONItem as a JSON array under the hood.

Var tags As New JSONItem
tags.Add("xojo")
tags.Add("desktop")
tags.Add("api")

Var jsonString As String = tags.ToString
// ["xojo","desktop","api"]

Nesting Things

Most APIs want nested payloads. You map this out by making separate JSONItem objects and attaching them to each other.

Var payload As New JSONItem
payload.Value("status") = "active"

Var user As New JSONItem
user.Value("id") = 982
user.Value("username") = "johndoe"

Var roles As New JSONItem
roles.Add("admin")
roles.Add("editor")

user.Value("roles") = roles // Attach the array to the user object
payload.Value("data") = user // Attach the user object to the main payload

Var jsonString As String = payload.ToString
// {"status":"active","data":{"id":982,"username":"johndoe","roles":["admin","editor"]}}

Part 2: Parsing JSON

To go the other direction, pass a raw JSON string straight into the constructor.

Reading a Flat Response

When a server hands you back a flat config or auth token, just pull the values right out.

Var rawJSON As String = "{""token"":""abc123xyz"",""expiresIn"":3600,""active"":true}"
Var response As New JSONItem(rawJSON)

Var token As String = response.Value("token")
Var expiresIn As Integer = response.Value("expiresIn")
Var isActive As Boolean = response.Value("active")

Handling Optional Keys with Lookup

If you use .Value("key") and the key isn’t in the JSON, Xojo throws a KeyNotFoundException. Instead of writing boilerplate If response.HasKey("key") Then checks everywhere, use .Lookup(). It lets you define a fallback value in line.

Var rawJSON As String = "{""username"":""johndoe""}"
Var response As New JSONItem(rawJSON)

// Returns "johndoe" because the key is present
Var user As String = response.Lookup("username", "anonymous") 

// Returns False because "forceSync" is missing from the JSON
Var isSyncForced As Boolean = response.Lookup("forceSync", False) 

Looping Over an Array

If an API hands you a list of database records:

Var rawJSON As String = "[{""id"":1, ""name"":""Alice""}, {""id"":2, ""name"":""Bob""}]"
Var userList As New JSONItem(rawJSON)

For i As Integer = 0 To userList.Count - 1
  Var currentUser As JSONItem = userList.ValueAt(i)

  Var id As Integer = currentUser.Value("id")
  Var name As String = currentUser.Value("name")

  System.DebugLog(id.ToString + ": " + name)
Next

Digging out Nested Nodes

This is where .Child() comes in handy. While .Value() returns a generic Variant (which you can’t chain directly), .Child("key") explicitly returns the nested object as a JSONItem. This allows for perfectly clean chaining.

Var rawJSON As String = "{""weather"":{""current"":{""temp"":22, ""condition"":""Sunny""}}}"
Var forecast As New JSONItem(rawJSON)

// Use .Child() to tunnel down into objects, then .Value() to pull the final primitive data 
Var temperature As Double = forecast.Child("weather").Child("current").Value("temp")
Var condition As String = forecast.Child("weather").Child("current").Value("condition")

Part 3: Identifying the Structure

APIs are notoriously inconsistent. Check the .IsArray property to figure out what structure you’re dealing with before parsing it, so your loops don’t crash when passing something unexpected.

Var rawJSON As String = "[""apple"", ""banana"", ""orange""]"
Var parsedData As New JSONItem(rawJSON)

If parsedData.IsArray Then
  System.DebugLog("Looks like an array with " + parsedData.Count.ToString + " items.")

  For i As Integer = 0 To parsedData.Count - 1
    System.DebugLog(parsedData.ValueAt(i).StringValue)
  Next
Else
  System.DebugLog("It's a standard dictionary.")
  If parsedData.HasKey("data") Then
    System.DebugLog(parsedData.Value("data").StringValue)
  End If
End If

That’s it. For more info on JSONItem, don’t forget to check the online documentation at: https://documentation.xojo.com/api/text/json/jsonitem.html

Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!