デコードされたJSONフィールドはnil値のみを提供し、変数に格納することはできません

orbek1815

これが私がデコードする必要のあるJSONです。その写真とテキストが下のリンクにあります(フォーマットが機能しないため、見栄えが悪くなります)。構造体で正しく表現したと確信しています。

ここに画像の説明を入力してください

{ "success": { "total": 1 }, "contents": { "quotes": [ { "quote": "The last time doesn't exist. It's only this time. And everything is going to be different this time. There's only now.", "author": "Bill Murray", "length": "118", "tags": [ "inspire", "present" ], "category": "inspire", "title": "Inspiring Quote of the day", "date": "2019-01-16", "id": null } ], "copyright": "2017-19 theysaidso.com" } }

Whenever I run my code, which attempts to take the fields from the JSON and store them into variables in order to display them in a UITableView, it fails. I test it by trying to make a label appear as with the author's name as its title. "author" is a field in the JSON. These are the important parts of the code:

Class ViewController: UITableViewController  {

...
var quoteArray = [Quote]()
//quoteArray Stores the quote objects that contain the fields I need
.....
//STRUCTS TO REPRESENT THE JSON
struct Quote: Decodable {
    let quote: String?
    let author: String?
    let length: String?
    let tags: [String]?
    let category: String?
    let title: String?
    let date: String?
}

struct WebsiteObjectStruct: Decodable {
    let success: SuccessStruct
    let contents: ContentsStruct
}

struct SuccessStruct: Decodable{
    let total: Int?
}

struct ContentsStruct: Decodable{
    let quotes: [Quote]?
    let copyright:  String?
}

.....

//FUNCTION WHERE DECODING HAPPENS

fileprivate func fetchJSON(){
        ...
        self.websiteObject = try decoder.decode(WebsiteObjectStruct.self, from: data)
        self.tableView.reloadData()
        ...
}
...

//CELL FOR ROW AT FUNCTION FOR TABLEVIEW

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cellId")
    let authorText = quoteArray[0].author
    cell.textLabel?.text = author.text
    //For quoteArray we are looking at zero index because in my JSON there
    // is ONLY EVER ONE element, located at index 0, in quoteArray
    return cell
}

}

The app runs and the the tableView is empty, it doesnt have the author's name (In this case bill murray). Anyway, here is the error message:

Failed to decode: typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array but found a dictionary instead.", underlyingError: nil))

It says it expected to decode an array but instead found a dictionary. Well I changed it one time to decode not an array but a struct, and had a variable declared in the class that was of type struct (the purpose of the struct mirrors the purpose of the array).

Short story is, I changed the code slightly to accomodate for the struct, and it could print the author's name to the console ONLY if the print statement was within the same coding brackets as the decoding statement. Still, it couldn't store it into a variable for use.

I don't think the problem is Array vs Dictionary but with the "underlyingError" the console talks about, that the Array is nil. No matter what type the variable is, whether Array or a Struct, the variable getting placed into the textField is always nil.

I get this error:

Fatal Error: unexpected found nil while unwrapping optional value

Perhaps an issue with threading or asynchrosity?

Update: this code works:

class MainNetworkManager{ //Request JSON Format from the wep API

static func fetchJSON(fetchUrl: String, quoteViewController: QuoteViewController) {
    let urlString = fetchUrl
    guard let url = URL(string: urlString) else { return }
    URLSession.shared.dataTask(with: url) { (data, _, err) in
        DispatchQueue.main.async {
            if let err = err {
                print("Failed to get data from url:", err)
                return
            }

            guard let data = data else { return }

            do {
                // link in description for video on JSONDecoder
                let decoder = JSONDecoder()
                // Swift 4.1
                decoder.keyDecodingStrategy = .convertFromSnakeCase
                //self.webStruct = try decoder.decode(WebsiteObjectStruct.self, from: data)
                //                        self?.quoteArray = quotesArray
                //                        self?.reloadInputViews()
                let tempStruct = try decoder.decode(WebsiteObjectStruct.self, from: data)

                //print(tempStruct.contents.quotes[0].length)
                quoteViewController.webStruct = tempStruct

                //quoteViewController.setupLabels(array: (tempStruct.contents.quotes))
                quoteViewController.setupLabels(obj: tempStruct)


            } catch let jsonErr {
                print("Failed to decode:", jsonErr)
            }
        }
        }.resume()
}
Aaron Cyrman

It's a little difficult to figure out the mistake with the code you posted. I think the problem could be with the type definition of the variable websiteObject. I created a a small playground to test it and your structs are fine.

I create a small project that works ok using your structs. You can check it out here: https://github.com/acyrman/StackOverflow54211226.

関連する変更は、fetchJSON関数にあります。self.websiteObjectどのように定義したかわからなかったを使用する代わりにlet websiteObject = try decoder.decode(WebsiteObjectStruct.self, from: data)、次のようなローカル変数を使用しました。次に、引用符を取得してquoteArray変数に割り当てます。

fileprivate func fetchJSON() {
    let urlString = "http://quotes.rest/qod.json?category=inspire"
    guard let url = URL(string: urlString) else { return }
    URLSession.shared.dataTask(with: url) { [weak self] (data, response, error) in
        if error != nil {
            self?.displayAlert("Error fetching data: \(String(describing: error?.localizedDescription))")
        }

        let decoder = JSONDecoder()
        do {
            guard let data = data else { throw NSError(domain: "this.app", code: -1, userInfo: nil) }

            let websiteObject = try decoder.decode(WebsiteObjectStruct.self, from: data)
            if let quotesArray = websiteObject.contents.quotes {
                DispatchQueue.main.async {
                    self?.quoteArray = quotesArray
                    self?.tableView.reloadData()
                }
            }
        } catch let error {
            self?.displayAlert("Error decoding json data: \(String(describing: error.localizedDescription))")
        }
    }.resume()
}

アプリの場合、http//quotes.rest/qod.json?category = inspireから見積もりを取得していますまた、info.plistでは、ATS設定を有効にして、https以外のURLからデータをフェッチできるようにすることが重要です。

ここに画像の説明を入力してください

コードは構造体をテストするためのものであり、クリーンなコードプロジェクトを期待しないでください;)

アプリコールfetchJSONviewDidLoad使用して、subtitleセルスタイル、このようなUIのルックスを:

ここに画像の説明を入力してください

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

javascriptで非表示フィールドに変更された値を表示することはできません

分類Dev

動的に作成された複数の入力フィールド値は、指定された数を超えることはできません

分類Dev

Visual Studioデバッガーは、dotPeekを使用してサードパーティの分解されたコードをデバッグするときに、パラメーターまたはローカル変数を表示できません。

分類Dev

オーバーライドされた格納プロパティで、getter / setterを持つ変数に初期値を設定することはできません

分類Dev

このコードは値を繰り返すことはありますか?繰り返されることはなく、格納された変数を必要としない数値が必要です

分類Dev

要素の値を変更するときに、AWKは複数のフィールドを認識しません

分類Dev

クエリ時に「複数の独立して繰り返されるフィールドを同時に出力することはできません」エラー

分類Dev

レコードセットフィールドを読み取ろうとしたときに、Access vbaがサブまたは関数をスローすることが定義されていないのはなぜですか?

分類Dev

シェル変数に格納されている行から空のフィールドを削除または削除します

分類Dev

JSON値を取得するために入力文字列を連結することはできません...しかしそれをハードコーディングすることはできます

分類Dev

保護されたシートのコードでセルの値を変更することはできません

分類Dev

JSON配列は長さとして「1」のみを提供し、ループすることはできません

分類Dev

ファイヤーストアから変数にフィールド値を格納できません

分類Dev

クラスのコンストラクターでフィールドを宣言して初期化したときに、フィールドがnullまたはデフォルト値のゼロに初期化されるのはなぜですか?

分類Dev

Qt作成者:「警告:コードモデルはインクルードされたファイルを渡すことができませんでした...」

分類Dev

実際の値を割り当てたばかりのnull許容フィールドはもうnullにできないことをコンパイラに納得させる、エレガントなkotlinの方法はありますか?

分類Dev

TypeError('フィードの値は tf.Tensor オブジェクトにすることはできません....) numpy 配列を提供していますが、

分類Dev

このフィールドをデータベースに保存する方法を理解できません。あなたはそれにタイプコンバーターを追加することを検討できます

分類Dev

Android-エラー:このフィールドをデータベースに保存する方法がわかりません。あなたはそれのために型コンバーターを追加することを検討できますか?

分類Dev

Railsは動的にネストされた形式(2レベル)で別の入力フィールドを追加することはできません

分類Dev

ハードコードされた値をcsprojのプロパティに置き換えることはできません

分類Dev

フィールドをnullにすることはできませんが指定されています

分類Dev

ケースクラスを使用してJSONをエンコードするときに、「データセットに格納されているタイプのエンコーダーが見つかりません」というエラーが発生するのはなぜですか?

分類Dev

フィールドの検証を確認する方法、選択した値を同じにすることはできませんか?

分類Dev

トレーニングは100%であり、動画から抽出した画像をディープラーニングモデルにフィードする方法にもかかわらず、検証の精度を向上させることはできません

分類Dev

Djangoは移行を行うことができません:フォロワー用のフォームフィールドをまだ作成できません。関連するモデル「self」がまだロードされていないため

分類Dev

変数を使用してフィールド内の配列メンバーにアクセスすることはできません

分類Dev

計算された変数は、setterとgetterの両方でのみ使用して、スーパークラスの格納されたプロパティをオーバーライドできます。

分類Dev

コードに間違いが見つかりません。リストを使用して操作と数値を格納しているのは電卓ですか?

Related 関連記事

  1. 1

    javascriptで非表示フィールドに変更された値を表示することはできません

  2. 2

    動的に作成された複数の入力フィールド値は、指定された数を超えることはできません

  3. 3

    Visual Studioデバッガーは、dotPeekを使用してサードパーティの分解されたコードをデバッグするときに、パラメーターまたはローカル変数を表示できません。

  4. 4

    オーバーライドされた格納プロパティで、getter / setterを持つ変数に初期値を設定することはできません

  5. 5

    このコードは値を繰り返すことはありますか?繰り返されることはなく、格納された変数を必要としない数値が必要です

  6. 6

    要素の値を変更するときに、AWKは複数のフィールドを認識しません

  7. 7

    クエリ時に「複数の独立して繰り返されるフィールドを同時に出力することはできません」エラー

  8. 8

    レコードセットフィールドを読み取ろうとしたときに、Access vbaがサブまたは関数をスローすることが定義されていないのはなぜですか?

  9. 9

    シェル変数に格納されている行から空のフィールドを削除または削除します

  10. 10

    JSON値を取得するために入力文字列を連結することはできません...しかしそれをハードコーディングすることはできます

  11. 11

    保護されたシートのコードでセルの値を変更することはできません

  12. 12

    JSON配列は長さとして「1」のみを提供し、ループすることはできません

  13. 13

    ファイヤーストアから変数にフィールド値を格納できません

  14. 14

    クラスのコンストラクターでフィールドを宣言して初期化したときに、フィールドがnullまたはデフォルト値のゼロに初期化されるのはなぜですか?

  15. 15

    Qt作成者:「警告:コードモデルはインクルードされたファイルを渡すことができませんでした...」

  16. 16

    実際の値を割り当てたばかりのnull許容フィールドはもうnullにできないことをコンパイラに納得させる、エレガントなkotlinの方法はありますか?

  17. 17

    TypeError('フィードの値は tf.Tensor オブジェクトにすることはできません....) numpy 配列を提供していますが、

  18. 18

    このフィールドをデータベースに保存する方法を理解できません。あなたはそれにタイプコンバーターを追加することを検討できます

  19. 19

    Android-エラー:このフィールドをデータベースに保存する方法がわかりません。あなたはそれのために型コンバーターを追加することを検討できますか?

  20. 20

    Railsは動的にネストされた形式(2レベル)で別の入力フィールドを追加することはできません

  21. 21

    ハードコードされた値をcsprojのプロパティに置き換えることはできません

  22. 22

    フィールドをnullにすることはできませんが指定されています

  23. 23

    ケースクラスを使用してJSONをエンコードするときに、「データセットに格納されているタイプのエンコーダーが見つかりません」というエラーが発生するのはなぜですか?

  24. 24

    フィールドの検証を確認する方法、選択した値を同じにすることはできませんか?

  25. 25

    トレーニングは100%であり、動画から抽出した画像をディープラーニングモデルにフィードする方法にもかかわらず、検証の精度を向上させることはできません

  26. 26

    Djangoは移行を行うことができません:フォロワー用のフォームフィールドをまだ作成できません。関連するモデル「self」がまだロードされていないため

  27. 27

    変数を使用してフィールド内の配列メンバーにアクセスすることはできません

  28. 28

    計算された変数は、setterとgetterの両方でのみ使用して、スーパークラスの格納されたプロパティをオーバーライドできます。

  29. 29

    コードに間違いが見つかりません。リストを使用して操作と数値を格納しているのは電卓ですか?

ホットタグ

アーカイブ