Has anyone been able to find a way to parse through JSON files in Swift 3? I have been able to get the data to return but I am unsuccessful when it comes to breaking the dat
Have you tried JSONSerialization.jsonObject(with:options:)?
var jsonString = "{" +
"\"Language\": {" +
"\"Field\":[" +
"{" +
"\"Number\":\"976\"," +
"\"Name\":\"Test\"" +
"}," +
"{" +
"\"Number\":\"977\"," +
"\"Name\":\"Test\"" +
"}" +
"]" +
"}" +
"}"
var data = jsonString.data(using: .utf8)!
let json = try? JSONSerialization.jsonObject(with: data)
Swift sometimes produces some very odd syntax.
if let number = json?["Language"]??["Field"]??[0]?["Number"] as? String {
print(number)
}
Everything in the JSON object hierarchy ends up getting wrapped as an optional (ie. AnyObject?). Array subscript returns a non-optional T. For this JSON, which is wrapped in an optional, array subscript returns Optional. However, Dictionary subscript returns an Optional. For this JSON, subscript returns the very odd looking
Optional (ie. AnyObject??).
json is an Optional.json?["Language"] returns an Optional> .json?["Language"]??["Field"] returns an Optional> .json?["Language"]??["Field"]??[0] returns an Optional.json?["Language"]??["Field"]??[0]?["Number"] returns an Optional> .json?["Language"]??["Field"]??[0]?["Number"] as? String returns an Optional.The Optional is then used by the if let syntax to product a String.
Final note: iterating the field array looks like this.
for field in json?["Language"]??["Field"] as? [AnyObject] ?? [] {
if let number = field["Number"] as? String {
print(number)
}
}
Swift 4 Update
Swift 4 makes this all much easier to deal with. Again we will start with your test data (""" makes this so much nicer).
let data = """
{
"Language": {
"Field":[
{
"Number":"976",
"Name":"Test"
},
{
"Number":"977",
"Name":"Test"
}
]
}
}
""".data(using: .utf8)!
Next we can define classes around the objects used in your JSON.
struct Object: Decodable {
let language: Language
enum CodingKeys: String, CodingKey { case language="Language" }
}
struct Language: Decodable {
let fields: [Field]
enum CodingKeys: String, CodingKey { case fields="Field" }
}
struct Field: Decodable {
let number: String
let name: String
enum CodingKeys: String, CodingKey { case number="Number"; case name="Name" }
}
The CodingKeys enum is how struct properties are mapped to JSON object member strings. This mapping is done automagically by Decodable.
Parsing the JSON now is simple.
let object = try! JSONDecoder().decode(Object.self, from: data)
print(object.language.fields[0].name)
for field in object.language.fields {
print(field.number)
}