0

I am attempting to decode an array of strings, where in the returned JSON is an array of strings but also contains nested arrays

Like:

{ "people": ["Alice", "Bob"], 
"departments": [["Accounts", "Sales"]]
}

My Swift code:

let decoder = JSONDecoder()
let model = try decoder.decode([String:[String]].self, from: dataResponse)
print(model as Any)

I want to be able to decode the departments, but each time I do it complains that:

Error typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [_DictionaryCodingKey(stringValue: "departments", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Expected to decode String but found an array instead.", underlyingError: nil))

I understand that this is because the decoder is expecting a string with an array of strings

I am wondering if I can also tell it to expect multiple, nested arrays of strings.

2
  • Pasting your JSON data into app.quicktype.io gives you a very reasonable start on how to model your Swift structs Commented Mar 3, 2019 at 17:30
  • I was not aware of this tool, but it looks great and much appreciated Commented Mar 3, 2019 at 17:52

2 Answers 2

3

You just need to create the appropriate structure and pass it to the decoder:

struct Root: Decodable {
    let people: [String]
    let departments: [[String]]
}

let decoder = JSONDecoder()
do {
    let model = try decoder.decode(Root.self, from: dataResponse)
     print(model.people)      // ["Alice", "Bob"]\n"
     print(model.departments) // [["Accounts", "Sales"]]\n"
} catch {
    print(error) 
}
Sign up to request clarification or add additional context in comments.

1 Comment

Ah I see. this has been bugging me for a while how decoder worked on multiple arrays - i can do it for single arrays, but it is appreciated and I certainly need to brush up on my skills
1

If you don't want to create structs (need just a piece of data, for example) here is an approach to consider.

let jsonData =  """
{ "people": ["Alice", "Bob"],
"departments": [["Accounts", "Sales"]],
"stores": [["Atlanta", "Denver"]]
}
""".data(using: .utf8)

if let jsonObject = try? JSONSerialization.jsonObject(with: jsonData!, options: []) as? [String: Any] {
    if let people = jsonObject["people"] as? [String] {
        print(people)
    }
    if let departments = jsonObject["departments"] as? [[String]] {
        print(departments)
    }
}

2 Comments

let jsonData = Data(""" { "people": ["Alice", "Bob"], "departments": [["Accounts", "Sales"]], "stores": [["Atlanta", "Denver"]] } """.utf8). Btw ptions: [] can be simply omitted and to unwrap jsonObject properly you need to add a parenthesis if let jsonObject = (try? JSONSerialization.jsonObject(with: jsonData)) as? [String: Any] {
Good idea, @Leo. Brevity is good as log as clarity doesn't suffer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.