为什么我的JSON请求失败超过50%?

时间:2018-07-06 17:37:53

标签: json swift

我正在制作一款拼字游戏,该游戏从Oxford Dictionary的API中获取单词。该应用程序提供了预期的单词,但其失败率高于我想要的水平。我的成功率约为25%至36%;大多数单词给出的结果都是nil,但这显然是我的错,而不是API的错。我想要更高的成功率,因为​​API不是免费的。还是这种命中率是主要API所特有的?

我知道我需要将其更改为Swift 4的JSON的Decodable ,但我还没有弄清楚那个问题。

您能在我的代码中找到导致完全简单的单词被跳过的任何内容,例如在任何词典中都存在的单音节单词吗?在代码的结尾,我在示例控制台日志中添加了成功和失败的单词。

func speakRandomWord() {
 //Now that a valid random word is selected, this where I make my API call.


   appId = "private"
   appKey = "private"
   language = "en"
   word = randomWord //I get the random word from Lexicontext, Oxford API doesn't support random words yet. I filter out entriest that aren't one word.
   regions = "gb"
   word_id = word.lowercased() 
   url = URL(string:"https://odapi.oxforddictionaries.com:443/api/v1/entries/\(language)/\(word_id)/regions=\(regions)")!
    var request = URLRequest(url: url)
    request.addValue("application/json", forHTTPHeaderField: "Accept")
    request.addValue(appId, forHTTPHeaderField: "app_id")
    request.addValue(appKey, forHTTPHeaderField: "app_key")

    let session = URLSession.shared
    print ("URLSession began...")
    dataAttempted += 1
    _ = session.dataTask(with: request, completionHandler: { data, response, error in
    if let httpResponse = response as? HTTPURLResponse {
    print("statusCode: \(httpResponse.statusCode)")

    if httpResponse.statusCode != 200 {

        print ("URLSession failed, trying again...")
        self.urlSessionFailed += 1
        self.selectRandomWord()
        self.speakRandomWord()
        }

   }

   DispatchQueue.main.async { [unowned self] in
   self.activitySpinner.stopAnimating()
   self.activitySpinner.isHidden = true
   self.theUserInput.becomeFirstResponder()
   self.repeatButton.isEnabled = true
   self.defineButton.isEnabled = true


}

    if let response = response,
        let data = data,
        let jsonData = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:AnyObject]

        {

if
let dictionary = jsonData as? [String: Any],

let results = dictionary["results"] as? [[String: Any]],
!results.isEmpty, case var result = results[0],

let lexicalEntries = result["lexicalEntries"] as? [[String: Any]],
!lexicalEntries.isEmpty, case var lexicalEntry = lexicalEntries[0],

let derivatives = lexicalEntry["derivatives"] as? [[String:Any]],
!derivatives.isEmpty, case var derivative = derivatives[0],

let pronunciations = lexicalEntry["pronunciations"] as? [[String: Any]],
!pronunciations.isEmpty, case var pronunciation = pronunciations[0],

let entries = lexicalEntry["entries"] as? [[String:Any]],
!entries.isEmpty, case var entry = entries[0],

    let senses = entry["senses"] as? [[String:Any]],
    !senses.isEmpty, case var sense = senses[0],

    let examples = sense["examples"] as? [[String:Any]],
    !examples.isEmpty, case var example = examples[0] 

//Now I pick out details from the JSON like audio, sample sentence, etc.

 {

if let theText = example.removeValue(forKey:"text") {

self.theText = String(describing:theText)
 print ("The value is \(self.theText)")

}


if let meaning = sense.removeValue(forKey:"short_definitions") {

self.newMeaning = String(describing:meaning)
print ("The short meaning is \(self.meaning)")

}


if let origin = entry.removeValue(forKey:"etymologies") {



    self.newEtymology = String(describing:origin)

    self.decoded2 = String(self.newEtymology.characters.filter({!"U0123456789".contains(String($0))}))

   // print ("The etymology is \(self.decoded2)")

            }

if let audioPath = pronunciation.removeValue(forKey:"audioFile") {
    print ("MP3 audio file for \(self.word) exists")
    print (audioPath)
    self.audioPaths.append(audioPath as! String)
    self.dataIsValid += 1
    self.successfulWords.append(self.word)


   self.path = String(describing:audioPath)
    self.repeatPath = self.path
    print (self.path)
   if let url = URL.init(string: self.path) {
    self.player = AVPlayer.init(url: url)
   self.player.play()
    }


}

else {
    print ("No audio data for \(self.word)!")
    self.dataFailed += 1
    self.audioFailed.append(self.word)
    self.selectRandomWord()


   }

}
    else {
    print ("\(self.randomWord) failed, reason unknown!")
    self.dataFailed += 1
    self.failedOtherReason.append(self.word)
    self.selectRandomWord()

       }
    }


}).resume()

}

 // Console results:
 //URL Session failures: 5
 //API attempts: 41.0
 //API successes: 15.0
 //API failures: 21.0
 //Successful Oxford API hit percentage: 36.5853658536585

 //These 15 words succeeded: ["denunciation", "strategic", "strategic",  "detract", "opaline", "opaline", "jurist", "exit", "throaty", "mother", "mother", "regroup", "early", "managerial", "recalcitrant"]

  //These 0 words had no audio: []

  //These words 21 words failed for an unknown reason: ["overlook", "lignin", "mandate", "evident", "anagrammatize", "avoirdupois", "extraterrestrial", "opaline", "cauterization", "malted", "clear", "snuggle", "fresno", "jurist", "streamline", "nonconforming", "trochee", "adventitia", "rudiment", "sculpturesque", "bicycle"]

1 个答案:

答案 0 :(得分:0)

没有足够的信息来调试此特定问题,但是您收到的JSON响应可能具有可选字段。对于某些响应,预期该字段为空。这部分代码,

  if
    let dictionary = jsonData as? [String: Any],
    let results = dictionary["results"] as? [[String: Any]],
    !results.isEmpty,
    case var result = results[0],
    let lexicalEntries = result["lexicalEntries"] as? [[String: Any]],
    !lexicalEntries.isEmpty,
    case var lexicalEntry = lexicalEntries[0],
    let derivatives = lexicalEntry["derivatives"] as? [[String:Any]],
    !derivatives.isEmpty,
    case var derivative = derivatives[0],
    let pronunciations = lexicalEntry["pronunciations"] as? [[String: Any]],
    !pronunciations.isEmpty, case var pronunciation = pronunciations[0],
    let entries = lexicalEntry["entries"] as? [[String:Any]],
    !entries.isEmpty,
    case var entry = entries[0],
    let senses = entry["senses"] as? [[String:Any]],
    !senses.isEmpty, case var sense = senses[0],
    let examples = sense["examples"] as? [[String:Any]],
    !examples.isEmpty,
    case var example = examples[0]
    //Now I pick out details from the JSON like audio, sample sentence, etc.
  {

需要拆分以处理(和报告)缺少的字段。那是20个布尔测试,所有测试都必须在“好的”路径执行之前通过。 可能发生的情况是您的字典访问失败。例如,如果字典不包含“ lexicalEntries”,则它将采用失败路径,并且不会按预期返回空数组。 >

确认相同的单词每次都失败。查看实际的JSON以查找失败的单词,并确保报告了每个字段。

更新:

if let response = response,
  let data = data,
  let jsonData = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:AnyObject]
{
  guard let dictionary = jsonData as? [String: Any] else {
    print("Error: dictionary was not returned by endpoint")
    return
  }
  guard let results = dictionary["results"] as? [[String: Any]] else {
    print("Error: no results array returned by endpoint")
    return
  }
  result = results.first
  ...