获取嵌套JSON中的每个对象

时间:2017-04-04 16:02:57

标签: ios json swift

所以在这里你可以看到我的方法获取JSON。我的问题是我希望我的循环遍历每个对象。没有一个物体像现在这样10次。我知道player["1"]导致它重复获取第一个对象,这只是为了示例。我需要获取每个player信息。有人可以解决这个问题并稍微解释一下情况。

var homeTeamPlayers: [MatchUp]? = []

let urlRequest = URLRequest(url: URL(string: "http://www.fibalivestats.com/data/586746/data.json")!)

func fetchHomeTeam() {

    let task = URLSession.shared.dataTask(with: urlRequest) { (data,response,error) in

        if error != nil {
            print(error!)
            return
        }

        homeTeamPlayers = [MatchUp]()

        do {
            let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject]

            if let teamsFromJSON = json["tm"] as? [String : AnyObject] {
                if let homeTeam = teamsFromJSON["1"] as? [String : AnyObject] {
                    if let player = homeTeam["pl"] as? [String : AnyObject] {
                        for _ in player {
                            let homeTeamPlayer = MatchUp()
                            if let firstPlayer = player["1"] as? [String : AnyObject] {
                                if let name = firstPlayer["name"] as? String {

                                    homeTeamPlayer.homeTeam_name = name

                                }
                            }

                            homeTeamPlayers?.append(homeTeamPlayer)
                        }
                    }
                }
            }    
        } catch let error {
            print(error)
        }   
    } 

    task.resume()
}

这是我想要获取的JSON ......

{

    tm: {
        1: {

            pl: {
                1: {

                    name: "R. Miniotas"

                },
                2: {

                    name: "T. Delininkaitis"

                },
                3: {

                    name: "V. Cizauskas"

                },
                4: {

                    name: "T. Klimavicius"

                },
                5: {

                    name: "V. Lipkevicius"

                },
                6: {

                    name: "M. LinkeviÄius"

                },
                7: {

                    name: "D. Seskus"

                },
                8: {

                    name: "T. Michnevicius"

                },
                9: {

                    name: "D. Gvezdauskas"

                },
                11: {

                    name: "A. Valeika"

                }
            }

3 个答案:

答案 0 :(得分:3)

您需要使用for (key, value) in语法枚举字典:

if let players = homeTeam["pl"] as? [String : Any] {
   for (_, value) in players {
       let homeTeamPlayer = MatchUp()
       if let currentPlayer = value as? [String : Any],
          let name = currentPlayer["name"] as? String {
          homeTeamPlayer.homeTeam_name = name
       }

       homeTeamPlayers?.append(homeTeamPlayer)
   }
}

但是为了避免空Matchup个实例,我建议

if let players = homeTeam["pl"] as? [String : Any] {
  for (_, value) in players {
       if let currentPlayer = value as? [String : Any],
          let name = currentPlayer["name"] as? String {
             let homeTeamPlayer = MatchUp()
             homeTeamPlayer.homeTeam_name = name
             homeTeamPlayers?.append(homeTeamPlayer)
       }   
   }
}

注意:Swift 3中的JSON字典是[String:Any],为什么homeTeamPlayers数组是可选的?

最后 - 像往常一样 - .mutableContainers在Swift中毫无意义。

答案 1 :(得分:1)

您的JSON数据是字典词典的字典。

看起来有一个外键“tm”(团队),然后包含每个团队的键“1”,“2”等字典,然后在团队内部,有更多字典再次使用球员的钥匙“1”,“2”,“3”等。这不是一个很好的结构。

如果您不关心从字典中获取项目的顺序,那么您可以使用以下语法:

for (key, value) in dictionary

...循环遍历字典中的所有键/值对,但您需要知道未获得键/值对的顺序。它有时会按键顺序给你输入,而不是按顺序给你。

如果订单很重要,那么您需要先获取密钥,对它们进行排序,然后获取项目(或其他一些技术)。获取按键排序的值可能如下所示:

let keys = dictionary.keys.sorted($0 < $1)

for aKey in keys {
   let aValue = dictionary[aKey]
   //Do whatever you need to do with this entry
}

编辑:

您的JSON数据需要进行一些编辑才能使其成为合法的JSON:

{
  "tm" : {
    "1" : {
      "pl" : {
        "7" : {
          "name" : "D. Seskus"
        },
        "3" : {
          "name" : "V. Cizauskas"
        },
        "8" : {
          "name" : "T. Michnevicius"
        },
        "4" : {
          "name" : "T. Klimavicius"
        },
        "11" : {
          "name" : "A. Valeika"
        },
        "9" : {
          "name" : "D. Gvezdauskas"
        },
        "5" : {
          "name" : "V. Lipkevicius"
        },
        "1" : {
          "name" : "R. Miniotas"
        },
        "6" : {
          "name" : "M. LinkeviÃÂius"
        },
        "2" : {
          "name" : "T. Delininkaitis"
        }
      }
    }
  }
}

(所有的键和值都必须用引号括起来,我需要添加结束括号来终止对象图)

我编写了上面的代码并将其读入JSON对象,然后将其写回JSON而没有空格。然后我将所有引号转换为\"

这是经过测试的代码,它将JSON解析为对象,然后通过相当多的错误检查来遍历您的数据结构:

let jsonString = "{\"tm\":{\"1\":{\"pl\":{\"7\":{\"name\":\"D. Seskus\"},\"3\":{\"name\":\"V. Cizauskas\"},\"8\":{\"name\":\"T. Michnevicius\"},\"4\":{\"name\":\"T. Klimavicius\"},\"11\":{\"name\":\"A. Valeika\"},\"9\":{\"name\":\"D. Gvezdauskas\"},\"5\":{\"name\":\"V. Lipkevicius\"},\"1\":{\"name\":\"R. Miniotas\"},\"6\":{\"name\":\"M. LinkeviÃius\"},\"2\":{\"name\":\"T. Delininkaitis\"}}}}}"
guard let data = jsonString.data(using: .utf8) else {
  fatalError("Unable to convert string to Data")
}

var jsonObjectOptional: Any? = nil
do {
  jsonObjectOptional = try JSONSerialization.jsonObject(with: data, options: [])
} catch {
  print("reading JSON failed with error \(error)")
}

guard let jsonObject = jsonObjectOptional as? [String: Any] else {
  fatalError("Unable to read JSON data")
}

//Fetch the value for the "tm" key in the outer dictionary
guard let teamsFromJSON = jsonObject["tm"] as? [String : Any] else {
  fatalError("Can't fetch dictionary from JSON[\"tm\"]")
}

let teamKeys = teamsFromJSON
  .keys                                                           //Fetch all the keys from the teamsFromJSON dictionary
  .sorted{$0.compare($1, options: .numeric) == .orderedAscending} //Sort the key strings in numeric order
print("teamsFromJSON = \(teamsFromJSON)")

//loop through the (sorted) team keys in teamKeys
for aTeamKey in teamKeys {
  guard let aTeam = teamsFromJSON[aTeamKey] as? [String: Any] else {
    print("Unable to read array of teams")
    continue
  }

  //Fetch the dictionary of players for this team
  guard let playersDict = aTeam["pl"] as? [String: Any] else {
    print("Unable to read players dictionary from team \(aTeamKey)")
    continue
  }

  //Fetch a sorted list of player keys
  let playerKeys = playersDict
    .keys
    .sorted{$0.compare($1, options: .numeric) == .orderedAscending}

  print("playerKeys = \(playerKeys)")

  //Loop through the sorted array of player keys
  for aPlayerKey in playerKeys {

    //Fetch the value for this player key
    guard let aPlayer = playersDict[aPlayerKey] as? [String: String] else {
      print("Unable to cast aPlayer to type [String: String]")
      continue
    }

    //Attempt to read the "name" entry for this player.
    guard let playerName = aPlayer["name"] else {
      continue
    }

    //Deal with a player in this team
    print("In team \(aTeamKey), player \(aPlayerKey) name = \(playerName)")
  }
}

if let jsonData = try? JSONSerialization.data(withJSONObject: jsonObject, options: []),
  let jsonString = String(data: jsonData, encoding: .ascii) {
  print("\n\njsonString = \n\(jsonString)")
}

该代码的输出是:

playerKeys = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "11"]
In team 1, player 1 name = R. Miniotas
In team 1, player 2 name = T. Delininkaitis
In team 1, player 3 name = V. Cizauskas
In team 1, player 4 name = T. Klimavicius
In team 1, player 5 name = V. Lipkevicius
In team 1, player 6 name = M. LinkeviÃius
In team 1, player 7 name = D. Seskus
In team 1, player 8 name = T. Michnevicius
In team 1, player 9 name = D. Gvezdauskas
In team 1, player 11 name = A. Valeika

(您的数据缺少玩家10的条目。)

答案 2 :(得分:0)

假设这是我的网址:

URL: https://maps.googleapis.com/maps/api/directions/json?origin=19.0176147,72.8561644&destination=26.98228,75.77469&sensor=false

在浏览器中输入上面提到的网址时,谷歌会给我一个JSON响应。 在这个回复中,我必须获取距离和持续时间的值。

所以我获取值的快捷代码是:

do{

        let data = try Data(contentsOf: url!)

        let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: AnyObject]

        if let routes = json?["routes"] as AnyObject? as? [[String: AnyObject]] {

            //print(routes)

            for r in routes {

                if let legs = r["legs"] as? [[String: AnyObject]] {

                    for l in legs {

                        //Start Address
                        print("Start Address: \((l["start_address"]!) as Any)")

                        // End Address
                        print("End Address: \((l["end_address"]!) as Any)")

                        //Distance
                        if let distance = l["distance"] as? [String: AnyObject] {

                            distanceResult = (distance["text"]!) as Any as? String

                            print("Distance: \(distanceResult!)")

                        }

                        // Duration
                        if let duration = l["duration"] as? [String: AnyObject] {

                            durationResult = (duration["text"]!) as Any as? String

                            print("Duration: \(durationResult!)")
                        }
                    }

                    googleResult = distanceResult+durationResult

                }
            }
        }
    }
    catch
    {
        distanceResult = ""
        durationResult = ""
        print("error in JSONSerialization")
    }

    if(googleResult != ""){
        googleResult = "Distance: \(distanceResult!), Duration: \(durationResult!)"
    }
    else{
        print("googleResult is nil")
        distanceResult = ""
        durationResult = ""
    }

    return googleResult