问题
So this is likely a very basic question, but I was curious how you would handle parsing a JSON object that returns as a single string using JSONSerialization in Swift. So I'm playing around with a free Harry Potter API and noticed that one of the routes returns a single string (https://www.potterapi.com/v1/sortinghat) and the response it gives is simply a single string of one of the four houses in Harry Potter.
"Ravenclaw"
Below was my attempt.
do {
let json = try JSONSerialization.jsonObject(with: data, options: []) as? String
print("json: \(json)")
} catch {
print("Error: \(error.localizedDescription)")
}
I thought simply typecasting as a String
would suffice but I just get the following error: "Error: The data couldn’t be read because it isn’t in the correct format."
I know there are better ways to parse JSON such as using Codable but I am just trying to understand how this would work before moving on to tackling that.
回答1:
JSONSerialization is the wrong tool for this. You want to use JSONDecoder, which is much more useful in Swift:
let json = Data("""
"Ravenclaw"
""".utf8)
let result = try JSONDecoder().decode(String.self, from: json)
Note that this requires iOS 13.1 or macOS 10.15.1. Otherwise you will need to use @vadian's answer.
回答2:
To deserialize a non-collection type you have to set the .allowFragments
option
let jsonString = """
"Slytherin"
"""
do {
if let json = try JSONSerialization.jsonObject(with: Data(jsonString.utf8), options: .allowFragments) as? String {
print("json: ", json)
}
} catch {
print("Error: ", error)
}
JSONDecoder
does not work, it calls underlying JSONSerialization
with no options.
The sense of deserializing a string to a string is another question, this does the same
if let json = String(data: data, encoding: .utf8) {
print("json: \(json)")
}
Edit: JSONDecoder
does work on iOS 13.1+ and macOS 10.15.1+
来源:https://stackoverflow.com/questions/59236554/how-to-use-swifts-jsonserialization-when-json-returns-a-single-string