Search code examples
jsonswiftalamofireswifty-json

JSON as raw string when enclosed within square brackets?


NOTE: THIS QUESTION IS ENTIRELY POINTLESS now as it turns out that what I wanted to achieve was in-fact possible using my original method. It was actually just me sending an empty parameter set that was causing the problems. Still, maybe someone somewhere might find one of the other methods suggested useful so I'll leave it here.

I've been using the following code snippet to convert JSON to a raw string perfectly for JSON that is enclosed within curly brackets:

AF.request("https://blahblah.com", method: .get, parameters: [:], encoding:JSONEncoding.default, headers: headers)
            .responseJSON { response in
                guard let data = response.data else { return }
                let json = try? JSON(data:data)
                if let jsonAsString = json?.rawString(){
                    self.consoleWindow.stringValue += jsonAsString
                }
           }

This works well when the JSON is enclosed in curly brackets like this:

{
        "blah1": true,
        "blah2": "ABCDEF",
        "blah3": "12345"
}

However, the JSON I'm now receiving is enclosed in square brackets, like this: (EDIT: Not necessarily always 3 elements, needs to be a general solution)

[
    {
        "blah1": true,
        "blah2": "ABCDEF",
        "blah3": "12345"
    }
]

When I use my original method, I'm just getting an empty string.

I am new to JSON and SwiftyJSON so I'm not sure how the square brackets change the structure of the JSON. How can I output the square bracketed JSON as a raw string like I have been doing with the curly bracketed JSON?

EDIT: For some context, I'm trying to create something like a console window that will output JSON of any format, with any number of elements.


Solution

  • If you simply want to get the string representation of your server's response, do this:

    AF.request("https://blahblah.com", method: .get, parameters: [:], encoding:JSONEncoding.default, headers: headers)
        .responseJSON { response in
            guard 
                let data = response.data,
                let string = String(bytes: data, encoding: .utf8) 
            else { 
                return 
            }
    
            self.consoleWindow.stringValue += string
        }
    }
    

    If you need to parse the received data into model objects, I'd recommend using swift's built-in Codable instead of SwiftyJSON for this.

    let json = """
    [
      {
        "blah1": true,
        "blah2": "ABCDEF",
        "blah3": "12345"
      }
    ]
    """.data(using: .utf8)!
    
    struct Bla: Codable {
        let blah1: Bool
        let blah2: String
        let blah3: String
    }
    
    do {
        // use [Bla].self to decode an array, or Bla.self for a single instance
        let bla = try JSONDecoder().decode([Bla].self, from: json)
        print(bla)
    } catch {
        print(error)
    }
    

    Lastly, I'd also recommend thinking about why you need Alamofire. Using URLSession/URLSessionDataTask isn't really that more complicated and having fewer 3rd party dependencies is almost always a plus, IMHO.