I have the folllowing Json response:
` [Body]:
{"id":"cmpl-6Z45N6vfd2312vdfqyYPb8aDRVe9Nft7vfnpoEsL","object":"text_completion","created":16738vfv15205,"model":"text-davinci-003","choices":[{"text":"\n1. Full Stack Developer\n2. Project Engineering Intern\n3. AI Programmer\n4. Systems Trade Studies Engineer\n5. BLE Technology Developer\n6. macOS Menu Bar App Developer\n7. Mobile App Developer\n8. Research Engineer\n9. Writing and Design Lab Researcher","index":0,"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":726,"completion_tokens":60,"total_tokens":786}}`
And I'm using SwiftyJson and Alamofire to parse the Json using the following code:
` AF.request(...).responseJSON { response in
print("response: \(response)")
switch response.result {
case .success(_):
if let JSON = response.value as! [[String : Any]]?{
print("JSON: \(JSON)")
let dic = JSON[0] as [String:AnyObject]?
print("TitularEmail : ",dic?["choices"])
}
break
case .failure(_):
print("There is an error")
break
}
}`
But it keeps breaking and I keep getting the error 'Thread 1: signal SIGABRT' at 'if let JSON = response.value as! [[String : Any]]?{'
Does anyone know what could've gone wrong? I've read through quite some threads but I can't seem to figure this out. Any info shall be appreciated.
CodePudding user response:
Using the built-in Decodable would be a much better alternative. At the risk of slightly wandering from the original SwiftyJSON question, I highly recommend using Decodable
to parse JSON (see also Encodable for writing and Codable for the combination of both). Here's an example of a very basic use of Decodable
. Supposed you want to parse the following:
{
"name": "New York City",
"mayor": "Eric Adams",
"population": 8468000
}
You can parse it super easily with Decodable
:
struct City: Decodable {
let name:String
let mayor:String
let population:Int
}
You can create an instance of City
in this example by taking the JSON– assume it is stored in a variable called jsonData
– and simply doing the following:
let NYC = try JSONDecoder().decode(City.self, from: jsonData)
You should highly consider this route because it can get a lot done with very little work.
You can also use JSONSerialization if you don't want to use the aforementioned ways of parsing it. Here is a simple tutorial on how to do that.
In your case, you can implement Decodable
to solve your problem like this:
var json = try! Data(contentsOf: URL(fileURLWithPath: "PATH TO FILE WITH EXAMPLE JSON TEXT"))
struct FirstStruct:Decodable {
let id:String
let object:String
let created:String //I'm calling this a string because, despite the lack of quotes, it has letters in it and cannot be an Int. You could also do something like Int? so it can fail safely if there are letters. I am adding quotes to the example text make it work.
let model:String
let choices:[SecondStruct]
let usage:ThirdStruct
}
struct SecondStruct:Decodable {
let text:String
let index:Int
let logprobs:String? //idk what type this is supposed to be from the text given
let finish_reason:String
}
struct ThirdStruct:Decodable {
let prompt_tokens:Int
let completion_tokens:Int
let total_tokens:Int
}
var test = try! JSONDecoder().decode(FirstStruct.self, from: json)
print(test.id)
print(test.usage.total_tokens) //these two examples show it clearly works here
Obviously, have a bit more care with error handling, try!
was just easier for the example.