

自作APIサーバからJSONをもらって、ログに表示しようとしています。

[code]

    let json: NSDictionary = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSDictionary
    
[/code]

の部分で

[code]

    The data couldn’t be read because it isn’t in the correct format.
    
[/code]

とエラーを吐かれてしまいますが、これは何が原因なのでしょうか  
APIへのアクセスはsessionのrisp変数の中身から、status code=200で成功していると思います

**SWIFTのコード**

[code]

    func someTask() {
            let url = URL(string: "My API Address")!
            let session = URLSession(configuration: URLSessionConfiguration.default)
            let task    = session.dataTask(with: url, completionHandler: {
                (data, resp, error) in
    
                if error != nil {
                    let str = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
                    print(str!)
    
                    print(error!.localizedDescription)
                    return
                }
    
                do {
    
                    let json: NSDictionary = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSDictionary
    
                    print(json["a"] ?? "a:none")
                    print(json["b"] ?? "b:none")
    
                } catch let error as NSError{
                    print(error.localizedDescription)
                }
    
            })
            task.resume()
        }
    
[/code]

**自作APIのコード**

[code]

    <html>
    <head>
    </head>
    <body>
    
    <?php
    
    $returnValue = array("a"=>1,"b"=>2);
    echo json_encode($returnValue);
    
    ?>
    
    </body>
    </html>
    
[/code]

[![実際に自作APIにアクセスしたところ](https://i.stack.imgur.com/vBl8J.png)](https://i.stack.imgur.com/vBl8J.png)


CC BY-SA 3.0
2016-11-06T13:19:00.853
30134
2016-11-06T13:57:03.733
8044
question
swift swift3
Swift3でJSONファイルをパースできない


あなたの **自作APIのコード** で返されるレスポンスは以下のような文字列に相当するバイト列になります。

[code]

    <html>
    <head>
    </head>
    <body>
    
    {"a":1,"b":2}
    
    </body>
    </html>
    
[/code]

このようにHTMLタグに埋もれたJSONレスポンスは、`JSONSerialization`ではパースすることはできません。

サーバ側のコードを次のように変えて試してみてください。

[code]

    <?php
    
    $returnValue = array("a"=>1,"b"=>2);
    echo json_encode($returnValue);
    
[/code]

* * *

Swift側のコードにもお勧めしたい修整があるので、箇条書きで挙げておきます。

(今回の問題については致命的な影響はないはずなので、以下は無視してもらっても構いません。)

  * エラー時の`data`は`nil`の可能性があるので、`data!`はアプリをクラッシュさせる恐れがある
  * エラー時にレスポンスを文字列変換するのに`NSString`を使う必要はない
  * エラー時のレスポンスはUTF-8で解釈できない可能性もあるので、`str!`も危険
[code]             if let data = data {

                let str = String(data: data, encoding: .utf8)
                print(str ?? "data not in UTF-8")
            } else {
                print("data is nil")
            }
    
[/code]

  * 結果が必ずJSON object(Swift側では`Dictionary`)になることを期待しているのなら、`options: .allowFragments`は不要

  * Swift 3では、`NSDictionary`(や`NSArray`)を使うより、Swiftの`Dictionary`(や`Array`)を使う癖をつけた方が後々楽になる
  * `as!`で型変換すると、JSON object以外のレスポンスが来た時にアプリがクラッシュする
[code]             if let json = try JSONSerialization.jsonObject(with: data!)
as? [String: Any] {

                print(json["a"] ?? "a:none")
                print(json["b"] ?? "b:none")
            } else {
                print("invalid JSON")
            }
    
[/code]


CC BY-SA 3.0
2016-11-06T13:57:03.733
30141
2016-11-06T13:57:03.733
13972
30134
answer