Ashh
Ashh

Reputation: 569

How to parse Array of JSON to array in Swift

I'm trying to parse JSON which is like below

[
  {
    "People": [
      "Jack",
      "Jones",
      "Rock",
      "Taylor",
      "Rob"
    ]
  },
  {
    "People": [
      "Rose",
      "John"

    ]
  },
  {
    "People": [
      "Ted"
    ]
  }
]

to an array which results in:

[ ["Jack", "Jones", "Rock", "Taylor", "Rob"] , ["Rose", "John"], ["Ted"] ]

which is array of arrays.

I tried with code below

if let path = Bundle.main.path(forResource: "People", ofType: "json") {
    let peoplesArray = try! JSONSerialization.jsonObject(
            with: Data(contentsOf: URL(fileURLWithPath: path)),
            options: JSONSerialization.ReadingOptions()
    ) as? [AnyObject]
    for people in peoplesArray! {
        print(people)
    }
}

when I print "people" I get o/p as

{
  People = (
    "Jack",
    "Jones",
    "Rock",
    "Taylor",
    "Rob"
  );
}
{
  People = (
    "Rose",
    "John"
  );
}
...

I'm confused how to parse when it has "People" repeated 3 times

Trying to display content in UITableView where my 1st cell has "Jack" .."Rob" and Second cell has "Rose" , "John" and third cell as "Ted"

PLease help me to understand how to achieve this

Upvotes: 17

Views: 86124

Answers (5)

anckydocky
anckydocky

Reputation: 76

I couldn't pasted it in a comment, it is too long or something

static func photosFromJSONObject(data: Data) -> photosResult {
    do {
        let jsonObject: Any =
                try JSONSerialization.jsonObject(with: data, options: [])

        print(jsonObject)

        guard let
              jsonDictionary = jsonObject as? [NSObject: Any] as NSDictionary?,
              let trackObject = jsonDictionary["track"] as? [String: Any],
              let album = trackObject["album"] as? [String: Any],
              let photosArray = album["image"] as? [[String: Any]]
                else {
            return .failure(lastFMError.invalidJSONData)
        }
    }
}

And the json was something like:

{
  artist: {
    name: Cher,
    track: {
        title: WhateverTitle,
        album: {
          title: AlbumWhatever,
          image: {
             small: "image.px",
             medium: "image.2px",
             large: "image.3px"}
       ....

Upvotes: 1

anckydocky
anckydocky

Reputation: 76

what you have here is first an array of 3 objects. each object is a dictionary where the key is people and the value is an array of strings. when you're trying to do jsonserialization, you have to cast it down to the expected result. So you have first an array of objects, then you have a dictionary with String: Any, then you obtain an array of String

let peoplesArray = try! JSONSerialization.jsonObject(with: Data(contentsOf: URL(fileURLWithPath: path)), options: []) as? [AnyObject]
guard let peoplesObject = peoplesArray["people"] as? [[String:Any]] else { return }
for people in peoplesObject {
    print("\(people)")
}

Upvotes: 1

Gabriel M.
Gabriel M.

Reputation: 128

let assume that the json is the encoded data

var arrayOfData : [String] = []
dispatch_async(dispatch_get_main_queue(),{
    for data in json as! [Dictionary<String,AnyObject>]
    {
        let data1 = data["People"]

        arrayOfData.append(data1!)
    }
})

You can now use the arrayOfData. :D

Upvotes: 1

mokagio
mokagio

Reputation: 17471

You can do this in an elegant and type safe way leveraging Swift 4 Decodable

First define a type for your people array.

struct People {
  let names: [String]
}

Then make it Decodable, so that it can be initialised with a JSON.

extension People: Decodable {

  private enum Key: String, CodingKey {
    case names = "People"
  }

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: Key.self)

    self.names = try container.decode([String].self, forKey: .names)
  }
}

Now you can easily decode your JSON input

guard
  let url = Bundle.main.url(forResource: "People", withExtension: "json"),
  let data = try? Data(contentsOf: url)
else { /* Insert error handling here */ }

do {
  let people = try JSONDecoder().decode([People].self, from: data)
} catch {
  // I find it handy to keep track of why the decoding has failed. E.g.:
  print(error)
  // Insert error handling here
}

Finally to get get your linear array of names you can do

let names = people.flatMap { $0.names }
// => ["Jack", "Jones", "Rock", "Taylor", "Rob", "Rose", "John", "Ted"]

Upvotes: 18

Bista
Bista

Reputation: 7893

 var peoplesArray:[Any] = [
    [
        "People": [
        "Jack",
        "Jones",
        "Rock",
        "Taylor",
        "Rob"
        ]
    ],
    [
        "People": [
        "Rose",
        "John"

        ]
    ],
    [
        "People": [
        "Ted"
        ]
    ]
  ]

 var finalArray:[Any] = []

 for peopleDict in peoplesArray {
    if let dict = peopleDict as? [String: Any], let peopleArray = dict["People"] as? [String] {
        finalArray.append(peopleArray)
    }
 }

 print(finalArray)

output:

[["Jack", "Jones", "Rock", "Taylor", "Rob"], ["Rose", "John"], ["Ted"]]

In your case, it will be:

if let path = Bundle.main.path(forResource: "People", ofType: "json") {
    let peoplesArray = try! JSONSerialization.jsonObject(with: Data(contentsOf: URL(fileURLWithPath: path)), options: JSONSerialization.ReadingOptions()) as? [Any]

    var finalArray:[Any] = []

    for peopleDict in peoplesArray {
        if let dict = peopleDict as? [String: Any], let peopleArray = dict["People"] as? [String] {
            finalArray.append(peopleArray)
        }
    }

    print(finalArray)
}

Upvotes: 14

Related Questions