简体   繁体   English

iOS / Swift:解析JSON数据和字典

[英]IOS/Swift: Parse JSON data and dictionary

I am trying to parse some nested JSON retrieved through an API but am having trouble isolating specific key-value pairs. 我正在尝试解析通过API检索的一些嵌套JSON,但在隔离特定键值对时遇到了麻烦。 In fact, I have some confusion over the difference between the JSON data and the dictionary obtained through serialization. 实际上,我对JSON数据和通过序列化获得的字典之间的差异有些困惑。

To retrieve the data I am using: 要检索我正在使用的数据:

let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {                                                 
                return
            } 

To convert the data to a JSON dictionary, I am doing 要将数据转换为JSON字典,我正在做

do {
                let stringDic = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]
            } catch let error {
                print(error)
            }

When printed, this produces nested output of the form: 打印时,将产生以下形式的嵌套输出:

Optional(["document_tone": {
    "tone_categories" =     (
                {
            "category_id" = "emotion_tone";
            "category_name" = "Emotion Tone";
  and so forth

My question is how can I get a unique value such as that for the key category_name ? 我的问题是如何获得唯一的值,例如键category_name

If I try to use 如果我尝试使用

let myCat = stringDic["category_name"]

Fix-it requires let document_tone = stringDic?["document_tone"] which if printed to console just prints whole dictionary over again. 修复它需要let document_tone = stringDic?["document_tone"] ,如果将其打印到控制台,则会再次打印整个词典。

Thanks in advance for any suggestions. 在此先感谢您的任何建议。

I think it's better to use Decodable 我认为使用Decodable更好

struct Root:Decodable {
     let documentTone : InnerItem 
} 
struct InnerItem:Decodable {
     let toneCategories: [BottomItem] 
}  
struct BottomItem:Decodable {
     let categoryId: String
     let categoryName: String 
}

do {
   let decoder = JSONDecoder()
   decoder.keyDecodingStrategy = .convertFromSnakeCase
   let result = try decoder.decode(Root.self, from: data)
   //print all names 
   result.documentTone.toneCategories.forEach {print($0.categoryName) }
} catch {
  print(error)
}

It's pretty easy: () is array, {} is dictionary and the compiler must know the static types of all subscripted objects: 这很简单:( ()是数组, {}是字典,编译器必须知道所有下标对象的静态类型:

if let documentTone = stringDic?["document_tone"] as? [String:Any],
   let toneCategories = documentTone["tone_categories"] as? [[String:Any]] {
   for category in toneCategories {
       print(category["category_name"])
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM