Ошибка при итерации по данным json словаря с помощью swift: не удалось найти перегрузку для «нижнего индекса», который принимает предоставленные аргументы

#json #dictionary #swift

#json #словарь #swift

Вопрос:

Я понял, как прочитать локальный файл json в моем проекте. Но теперь у меня возникают проблемы с итерацией по нему. Вот мои необработанные данные json:

 {
    "locations": [
                  {
                  "title": "The Pump Room",
                  "place": "Bath",
                  "latitude": 51.38131,
                  "longitude": -2.35959,
                  "information": "The Pump Room Restaurant in Bath is one of the city’s most elegant places to enjoy stylish, Modern-British cuisine.",
                  "telephone": " 44 (0)1225 444477",
                  "url": "http://www.romanbaths.co.uk",
                  "visited" : true
                  },
                  {
                  "title": "The Eye",
                  "place": "London",
                  "latitude": 51.502866,
                  "longitude": -0.119483,
                  "information": "At 135m, the London Eye is the world’s largest cantilevered observation wheel. It was designed by Marks Barfield Architects and launched in 2000.",
                  "telephone": " 44 (0)8717 813000",
                  "url": "http://www.londoneye.com",
                  "visited" : false
                  },
                  {
                  "title": "Chalice Well",
                  "place": "Glastonbury",
                  "latitude": 51.143669,
                  "longitude": -2.706782,
                  "information": "Chalice Well is one of Britain's most ancient wells, nestling in the Vale of Avalon between the famous Glastonbury Tor and Chalice Hill.",
                  "telephone": " 44 (0)1458 831154",
                  "url": "http://www.chalicewell.org.uk",
                  "visited" : true
                  },
                  {
                  "title": "Tate Modern",
                  "place": "London",
                  "latitude": 51.507774,
                  "longitude": -0.099446,
                  "information": "Tate Modern is a modern art gallery located in London. It is Britain's national gallery of international modern art and forms part of the Tate group.",
                  "telephone": " 44 (0)20 7887 8888",
                  "url": "http://www.tate.org.uk",
                  "visited" : true
                  },
                  {
                  "title": "Eiffel Tower",
                  "place": "Paris",
                  "latitude": 48.858271,
                  "longitude": 2.294114,
                  "information": "The Eiffel Tower (French: La Tour Eiffel, is an iron lattice tower located on the Champ de Mars in Paris.",
                  "telephone": " 33 892 70 12 39",
                  "url": "http://www.tour-eiffel.fr",
                  "visited" : false
                  },
                  {
                  "title": "Parc Guell",
                  "place": "Barcelona",
                  "latitude": 41.414483,
                  "longitude": 2.152579,
                  "information": "Parc Guell is a garden complex with architectural elements situated on the hill of El Carmel in the Gràcia district of Barcelona.",
                  "telephone": " 34 902 20 03 02",
                  "url": "http://www.parkguell.es",
                  "visited" : false
                  }
                  ]
}
  

Вот как я читаю и анализирую его:

   func readLocationData() {

        let bundle = NSBundle.mainBundle()
        let path = bundle.pathForResource("locations", ofType: "json")
        let content : NSString = NSString.stringWithContentsOfFile(path) as NSString

        let locationData:NSData = content.dataUsingEncoding(NSUTF8StringEncoding)

        var error: NSError?

        var jsonDict:Dictionary = NSJSONSerialization.JSONObjectWithData(locationData, options: nil, error: amp;error) as Dictionary<String, AnyObject>

        if let locations : AnyObject = jsonDict["locations"] {
            if let information: String = locations["information"] {
               // I get error here: Could not find an overload for 'subscript' that accepts the supplied arguments
            }
        }

    }
  

Теперь, как мне получить доступ к внутренним ключам, таким как title , place и location ? Все, что я пытаюсь внутри цикла, выдает ошибку приведения, например:

 Could not find an overload for 'subscript' that accepts the supplied arguments
  

Ответ №1:

Давайте посмотрим, к каким типам относятся различные части JSON: jsonDict это словарь, который имеет массив в качестве своего единственного значения, и jsonDict["locations"] массив других словарей. Вы должны использовать Dictionary<String, Any> for jsonDict , и тогда вам повезет позже:

 var jsonDict:Dictionary = NSJSONSerialization.JSONObjectWithData(locationData, options: nil, error: amp;error) as Dictionary<String, Any>
let locations: NSArray? = jsonDict["locations"] as? NSArray

if locations {
    for location: AnyObject in locations! {
        if let information = location as? NSDictionary {
            println(information)
        }
    }
}
  

Комментарии:

1. это выдает ошибку: Could not find an overload for 'subscript' that accepts the supplied arguments в let locations... строке

2. Хорошо, я думаю, мы близки. Теперь я получаю thread exc ошибку времени выполнения: fatal error: value failed to bridge from Objective-C type to a Swift type (lldb)

3. Возможно, это ошибка компилятора / Swift — переключение на базовые типы устраняет проблему — см. Выше

4. Нет — ошибка получения в этой строке: let locations: NSArray? = jsonDict["locations"] as? NSArray : fatal error: value failed to bridge from Objective-C type to a Swift type

5. Это странно — для меня просматривается весь файл JSON. Вы уверены, что JSON загружается правильно?

Ответ №2:

У вас есть словарь, содержащий одну запись «locations», которая представляет собой массив словарей.

Попробуйте это:

 // I'm using NSDictionary since it is easier to work with when you don't know the object // // types  but you can convert it later with explicit data types

if let results = jsonDict["locations"] as NSDictionary[] {
    for item in results {
        var title = item["title"] as String
    }
}
  

Примечание: я сам не запускал этот код, но вы, я думаю, должны понять идею.

Комментарии:

1. нет — я получаю ошибку: «Не удается преобразовать тип выражения ‘NSDictionary’ в тип ‘NSDictionary»

2. Из любопытства, вы запускаете это на игровой площадке?

3. Также удалено второе приведение результатов, не требуется

4. с помощью этого решения я получаю fatal error: value failed to bridge from Objective-C type to a Swift type (lldb)

5. Добавьте «как строку» или «как NSString» в заголовок