iOS/Swift/SwiftyJSON:解析IBM Watson Tone Analyzer API嵌套JSON
看起来你踩了JSON路径匹配的坑啦!你的代码里用了["results"][0],但看Watson返回的JSON结构,根本没有results这个节点,这就是输出nil的核心原因。我来帮你梳理正确的解析步骤:
首先,先明确Watson Tone Analyzer返回的JSON层级:
- 最外层是
document_tone对象 - 里面的
tone_categories是一个数组,包含三类色调(情感、语言、社交) - 我们需要的情感色调(anger、disgust这些)在
category_id为emotion_tone的分类下的tones数组里
第一步:定义数据模型(可选但推荐)
先定义一个结构体来存储单个色调的信息,这样后续处理数组会更清晰:
struct EmotionTone { let toneId: String // 比如"anger" let score: Double // 对应的分值 }
第二步:正确解析JSON
// 假设`value`是你从API获取的原始数据转成的JSON对象 let json = JSON(value) // 1. 先获取document_tone节点 guard let documentTone = json["document_tone"].dictionary else { print("无法解析document_tone节点") return } // 2. 获取tone_categories数组 guard let toneCategories = documentTone["tone_categories"]?.array else { print("无法获取tone_categories数组") return } // 3. 筛选出情感色调的分类(category_id为emotion_tone) guard let emotionCategory = toneCategories.first(where: { $0["category_id"].string == "emotion_tone" }) else { print("未找到情感色调分类") return } // 4. 解析情感色调的tones数组,转成我们定义的模型数组 guard let emotionTonesArray = emotionCategory["tones"].array else { print("无法获取情感tones数组") return } let emotionTones = emotionTonesArray.compactMap { toneJson -> EmotionTone? in // 提取tone_id和score,注意score是字符串类型,需要转成Double guard let toneId = toneJson["tone_id"].string, let scoreStr = toneJson["score"].string, let score = Double(scoreStr) else { return nil } return EmotionTone(toneId: toneId, score: score) } // 现在emotionTones就是你要的每段文本对应的对象数组(当前是单文档的情况,数组里有5个元素对应5种情感) print(emotionTones) // 如果需要转成["anger": 0.218727, "disgust": 0.210102...]这样的字典格式,也可以这样做: let toneDictionary = Dictionary(uniqueKeysWithValues: emotionTones.map { ($0.toneId, $0.score) }) print(toneDictionary)
为什么你的代码会返回nil?
你的代码里用了JSON(value)["results"][0]["anger"],但Watson的返回里没有results这个层级,直接导致后续的所有取值都是nil。只要修正路径,就能正确提取到数据啦。
如果你的API返回的是多句子/多段落的分析结果(会有sentences_tone节点),处理逻辑类似,只需要遍历sentences_tone数组,每个句子对象里再找对应的tone_categories即可。
内容的提问来源于stack exchange,提问作者user6631314
相关产品推荐
相关产品推荐

