質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

1796閲覧

[swift4 json] Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional valueについて

pepper0

総合スコア20

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2018/10/03 07:54

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

プログラミング初心者です。
現在sfift4にて、jsonファイルを読み込もうとしました。
ビルドは成功したのですが、以上のようなエラーが発生しました。
エラーを調べ、オプショナル型に問題が発生していることは分かったのですが、具体的にどのように直せば良いかわかりませんでした。

発生している問題・エラーメッセージ

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

該当のソースコード

import UIKit import Foundation class ViewController: UIViewController{ struct Animal: Codable { let park: String let animals: [String] let nickname: Dictionary<String, String> } func getJSONData() throws -> Data? { guard let path = Bundle.main.path(forResource: "animal", ofType: "json") else { return nil } let url = URL(fileURLWithPath: path) return try Data(contentsOf: url) } override func viewDidLoad() { super.viewDidLoad() guard let data = try? getJSONData() else { return } guard let animals = try? JSONDecoder().decode(Animal.self, from: data!) else { return } //jsonデータ出力 print("(animals.park) park") animals.animals.forEach({(animal) in print("animal:(animal)") }) animals.nickname.forEach({(animal, nickname) in print("(nickname) は (animals.park) 公園にいる (animal) のニックネームです") }) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }

試したこと

過去にあった質問を参照し、プログラムし直してみましたが上手くいきませんでした。
https://teratail.com/questions/100161

補足情報(FW/ツールのバージョンなど)

初歩的なミスだと思いますが、よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2018/10/03 08:00

エラーはどこで出ているのでしょうか?
pepper0

2018/10/09 07:47

実行時にエラーが発生しました。恐らくjsonファイルがプロジェクトに組み込んでいないためだと思われます。
fuzzball

2018/10/09 08:09

「いつ」ではなく「どこ」と聞いているのですが。
pepper0

2018/10/09 09:11 編集

失礼しました。override func viewDidLoad()内の、 guard let animals = try? JSONDecoder().decode(Animal.self, from: data!) else { return }に、 Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional valueというエラーです。
pepper0

2018/10/09 09:21

問題が解決しました。コメントしていただきありがとうございました。
guest

回答2

0

これは回答ではありません。 razuma さんの回答の補足説明です。

let data01 = try? getJSONData()

のとき、data01の型は Optional<Data> ではなく Optional<Optional<Data>> です。

getJSONData()の戻り値の型はOptional<Data>ですので、try?によってさらに Optional に包まれます。

ですので

guard let data = try? getJSONData() else { ... }

とすると1度だけアンラップされてdataは Optional<Data> となります。

このとき、getJSONData() が例外を投げたときは data がnilとなりelse節に処理が移りますが、
getJSONData()がnilを返したときは dataは Optional<nil>となり、これはnilではないためelse節には移りません。

Optional<Optional<Data>>の外側のOptionalはtry?由来のもの、内側のOptionalはgetJSONData()由来のものです。gurad節などは最も外側のOptionalをアンラップします。

そのため現状を維持しつつguardを機能させるためには

guard let either = try? getJSONData(), let data = either else { ... }

のようにする必要があります。

あるいは

enum ReadError: Error { case notFound } func getJSONData() throws -> Data { guard let path = Bundle.main.path(forResource: "animal", ofType: "json") else { throw ReadError.notFound } ... } ... // このdataはData型 guard let data = try? getJSONData() else { ... }

のようにgetJSONData()の戻り値に Optional は使用せず、全て例外を投げるようにします。

投稿2018/10/03 09:30

MasakiHori

総合スコア3384

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

こちらを参考にされているのだと思いますが
Swift4でJSONファイルを簡単に読み込む

animal.jsonファイルが読み込めずに
guard let path = Bundle.main.path(forResource: "animal", ofType: "json") else { return nil }
でnilのエラーが出てしまっていると思うので
animal.jsonと言うjsonファイルを作成して、プロジェクトに取り込んでください。

イメージ説明

=====コメントに対する回答追記
実際、今動かしているコードがどのようなものなのかはわかりませんが
参考サイトに書いてあるものだけですと、JSONを読み込んで、取得できたデータをprintで表示しているだけになっていますので、独自でビューに描画することをしていないのであれば真っ白なままです。
printはXcodeの画面下にあるconsoleに文字を表示するものなので

higashiyama park animal:cat animal:dog animal:monkey animal:rabbit jiro は higashiyama 公園にいる monkey のニックネームです。 tama は higashiyama 公園にいる cat のニックネームです。

上記のような内容がログとして表示されているのと思われます。
(JSONを扱ってなにか具体的にしたいことなどがありましたでしょうか?)

投稿2018/10/03 08:30

編集2018/10/09 08:12
razuma

総合スコア1313

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pepper0

2018/10/09 07:59

コメントが遅れました。回答していただきありがとうございます。 はい、そちらの記事を参考にしました。 回答を拝見し、拡張子を.jsonにしたテキストファイルをドラッグして、プロジェクトに組み込みました。 しかし、実行した結果としてエラーは出ませんでしたが、シュミレーターの画面が真っ白なままでした。 私のやり方が間違っているのでしょうか? 検索しても有益な情報が出てこないため、教えていただければ幸いです。
pepper0

2018/10/09 09:36

私の確認不足で、無事コンソールに表示されていました。 ありがとうございました! はい、pythonとjsonの間でデータの送受信を行い、受け取ったデータをボタンやテキストなどのUI部品に表示させ、処理したデータをpythonに送ることを現在の目的としています。
razuma

2018/10/09 09:41

なるほど、とりあえずデータを扱えるようになったことで問題がなさそうであれば良かったです。
pepper0

2018/10/10 00:47

はい、ありがとうございました。 また機会がありましたら、よろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問