Sam Soffes

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! (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 = .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! object, options: [.prettyPrinted])

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

  // Print the result

(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 :)