Debugging JSON Data in LLDB — Hi, I’m Sam

Hi, I’m Sam

This is my blog. I also have a website thing.

Debugging JSON Data in LLDB

Posted on

Recently, I added a snippet to my ~/.lldbinit for an easy way to print JSON in LLDB. It has saved me a ton of time, so I thought it was worth explaining.

Here’s the snippet:

command regex json 's/(.+)/expr let input = %1; print(String(data: try! JSONSerialization.data(withJSONObject: (input is String ? try! JSONSerialization.jsonObject(with: (input as! String).data(using: .utf8)!, options: []) : (input is Data ? (try! JSONSerialization.jsonObject(with: input as! Data, options: [])) : input as! Any)), options: [.prettyPrinted]), encoding: .utf8)!)/'

Let’s look at it in an easier to read format. Here’s some Swift psuedocode:

func json(input: Any) {
  // Ensure we’re working with a deserialized JSON object
  let object: Any
  if let string = input as? String, let data = string.data(using: .utf8) {
    // If the input was `String`, deserialize it
    object = try! JSONSerialization.jsonObject(with: data, options: []))
  } else if let data = input as? Data {
    // If the input was `Data`, deserialize it
    object = try! JSONSerialization.jsonObject(with: input, options: []))
  } else {
    object = input
  }

  // Convert the object pretty printed JSON data
  let jsonData = try! JSONSerialization.data(withJSONObject: object, options: [.prettyPrinted])

  // Convert the pretty printed JSON data to a `String`
  let jsonString = String(data: jsonData, encoding: .utf8)!

  // Print the result
  print(jsonString)
}

(Since we’re just using this in the console there are lots of try!s and !s. Of course, you wouldn’t normally write Swift like this.)

Here’s how it works in action:

(lldb) json data
{
  "given_name": "Sam",
  "family_name": "Soffes"
}

Instead of po, you can now use the new json command to pretty print the JSON data or a JSON serializable type (dictionary, array, etc.)

Either copy and paste the snippet into your LLDB console to add the command or add the snippet to ~/.lldbinit to make it always available.

Hopefully this saves you some time debugging network responses :)