0

json response: "result": {

   "user_images": [
        {
            "id": 113,
            "user_id": "160",
            "image": "1617349564.jpg",
            "image_title": "33"
          
        },
        {
            "id": 112,
            "user_id": "160",
            "image": "1617349541.jpg",
            "image_title": "22"
           
        },
        {
            "id": 111,
            "user_id": "160",
            "image": "1617349528.jpg",
            "image_title": "11"
        },
        ........

code: with this code i am getting response like above means all user_images array coming... but here i need image_title how to get that.. if i run for loop getting error.. pls do help

  if let code = ((response.dict?["result"] as? [String : Any])){
      let userImages = code["user_images"] as? [String : Any]

   }

how to get image_title value from above array of dictionaries

3
  • 2
    I will suggest go for Codables. If you want to get it from here, you can use userImages[0].image_title to get the first one and you can use a loop to get all of them and put userImages in if let userImages = code["user_images] as? [String: [String:Any]]. Commented Apr 5, 2021 at 14:47
  • 2
    JSON is a pretty simple text format. There are only two (2) collection types, array [] and dictionary {}. The value for user_images is clearly an array but you treat it as dictionary. Commented Apr 5, 2021 at 14:50
  • @Rob, yes i want all image_title how? Commented Apr 5, 2021 at 14:50

2 Answers 2

2

Sol 1

if let code = response.dict?["result"] as? [String : Any]  {
  if let userImages = code["user_images"] as? [[String : Any]] {
      for item in userImages {
         print(item["image_title"])
      } 
   } 
}

Sol 2

if let code = response.dict?["result"] as? [String : Any]  { 
   do { 
       let data = try JSONSerialization.data(withJSONObject: code) 
       let decoder = JSONDecoder() 
       decoder.keyDecodingStrategy = .convertFromSnakeCase 
       let res = try decoder.decode(Result.self, from: data) 
       let titles = res.userImages.map { $0.imageTitle } 
       print(titles) 
   }
   catch {
       print(error)
   } 
}

// MARK: - Result
struct Result: Codable {
    let userImages: [UserImage]
 
} 
// MARK: - UserImage
struct UserImage: Codable {
    let id: Int
    let userId, image, imageTitle: String
}
Sign up to request clarification or add additional context in comments.

3 Comments

Just to add to @Sh-Khan's answer. The reason for the [[String:Any]] is because you're attempting to set code as a Dictionary of String : Any whereas the JSON is an Array of Dictionary String : Any. It's easy to look at it and think that you're using just an array, but that's not the case.
yes if i run for loop also got this error For-in loop requires '[String : Any]?' to conform to 'Sequence'; did you mean to unwrap optional?
You should probably safely unwrap the result of code. Notice the ? in as? that means you're assuming it's an optional value. If you use something like guard let safeCode = code else { return } You'll be able to continue safely. Coding tip, try your best to always safely unwrap any ? and NEVER use !
1

Code from @Sh_Khan

if let code = response.dict?["result"] as? [String : Any]  {
  //You're using "as?" which means you're casting as an optional type. 
  //One simple solution to this is here where it's unwrapped using "if let"
  if let userImages = code["user_images"] as? [[String : Any]] {
      // [String:Any] is a Dictionary
      // [[String:Any]] is an Array of Dictionary
      for item in userImages {
         print(item["image_title"])
      } 
   } else {
      // We didn't unwrap this safely at all, do something else. 
}

Let's dive into this a little bit. This structure is a JSON Object

    {
        "id": 113,
        "user_id": "160",
        "image": "1617349564.jpg",
        "image_title": "33"
    }

But it's only a JSON object when it stands alone. Adding a key, or in this example user_images makes it a dictionary. Notice that the [ is not wrapped around it. Meaning it's a standalone dictionary. If this was your object, and this alone, your original code would work, but you're dealing with an Array of Dictionaries.

"user_images":
    {
        "id": 113,
        "user_id": "160",
        "image": "1617349564.jpg",
        "image_title": "33"
    }

This line of code essentially means that you're expecting to get back that Array of Dictionary. Bear in mind, each value for the dictionary is not an array value, which is why you don't see something like this [[[String: Any]]] because the data isn't nested like that.

if let userImages = code["user_images"] as? [[String : Any]]

What's this about optionals?

An optional is basically a nil possible value that can be returned. Typically when working with JSON you cannot guarantee that you'll always receive a value for a given key. It's even possible for a key value pair to be completely missing. If that were to happen you'd end up with a crash, because it's not handled. Here are the most common ways to handle Optionals

var someString: String? //This is the optional one
var someOtherString = "Hello, World!" //Non-optional

if let unwrappedString1 = someString {
   //This code will never be reached
} else {
   //This code will, because it can't be unwrapped.
}

guard let unwrappedString2 = someString else {
   //This code block will run
   return //Could also be continue, break, or return someValue
} 

//The code will never make it here.
print(someOtherString)

Furthermore, you can work with optionals by chain unwrapping them which is a nifty feature.

var someString: String?
var someInt: Int?
var someBool: Bool?

someString = "Hello, World!"

//someString is not nil, but an important distinction to make, if any
//fail, ALL fail.
if let safeString = someString,
   let safeInt = someInt,
   let safeBool = someBool {
      //If the values are unwrapped safely, they will be accessible here.
      //In this case, they are nil, so this block will never be hit.
      //I make this point because of scope, the guard statement saves you from the 
      //scoping issue present in if let unwrapping.
      print(safeString)
      print(safeInt)
      print(safeBool)
}

guard let safeString = someString,
      let safeInt = someInt, 
      let safeBool = someBool {
         //This will be hit if a value is null
      return
}

//However notice the scope is available outside of the guard statement, 
//meaning you can safely use the values now without them being contained
//to an if statement. Despite this example, they would never be hit.
print(safeString)
print(safeInt)
print(safeBool)

Comments

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.