簡體   English   中英

使用 JSONDecoder 解碼 object 的打印 output 時遇到問題

[英]Having trouble with print output of object decoded with JSONDecoder

我正在嘗試解碼 swift 中的 JSON 字符串,但在解碼后訪問屬性時遇到一些奇怪的問題。

這是我從本地存儲的 JSON 文件中檢索到的 JSON 文件的內容

[
  {
    "word": "a",
    "usage": [
      {
        "partOfSpeech": "determiner"
      }
    ]
  }
]

這是訪問 JSON 文件屬性的代碼

struct WordDictionary : Codable {
    var word: String
    var usage: [Usage]
}

struct Usage: Codable {
    var partOfSpeech: String
}
                
if let url = Bundle.main.url(forResource: FILE_NAME, withExtension: "json") {
    do {
        let data = try Data(contentsOf: url)
        let decoder = JSONDecoder()
        
        let jsonData = try decoder.decode([WordDictionary].self, from: data)
        print(jsonData[0].word) //Outputs "a"
        print(jsonData[0].usage) //Outputs "[MyApp.AppDelegate.(unknown context at $102a37f00).(unknown context at $102a38038).Usage(partOfSpeech: "determiner")]"

    } catch {
        print("error:\(error)")
    }
}

如您所見,當我嘗試print(jsonData[0].usage)時,我在獲取“Usage”屬性之前收到了一系列未知數據消息。 當我打印這一行時,我只想看到determiner ,我不確定關於“未知上下文”的序言是什么。

我還在AppDelegatedidFinishLaunchingWithOptions function 中運行這段代碼。

我不確定我錯過了什么。 幾天來我一直在嘗試尋找解決方案並嘗試不同的方法,但仍然無法獲得所需的 output,我們將不勝感激。

如果您希望某個類型在將其實例插入字符串時能夠很好地打印,則需要使其符合CustomStringConvertible

該協議聲明了一個屬性: description ,當字符串插值遇到符合它的 object 時,它會使用description返回的字符串。

你需要這樣的東西:

extension Usage: CustomStringConvertible
{
    var description: String 
    {
        return "{ \"partOfSpeech\" : \"\(partOfSpeech)\" }"
    }
}

如果你想打印一個 JSON 之類的*字符串。

另一種方法是使用 JSONEncoder 重新編碼JSONEncoder並將數據轉換為String 這要重得多,但對於更復雜的物體來說可能是更好的選擇。

* JSON 之類的,因為換行符和制表符之類的東西不會被轉義符替換,字符串中出現的"\也不會被轉義。

tl;博士

您在類型的描述中看到“未知上下文”,因為它是在 function 中定義的。您可以通過將這些類型定義移到 function 之外或實現您自己的CustomStringConvertible一致性來解決此問題。


這是你在哪里定義你的類型的問題。

考慮:

class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        struct WordDictionary: Codable {
            var word: String
            var usage: [Usage]
        }

        struct Usage: Codable {
            var partOfSpeech: String
        }

        do {
            let url = Bundle.main.url(forResource: "test", withExtension: "json")!
            let data = try Data(contentsOf: url)
            let words = try JSONDecoder().decode([WordDictionary].self, from: data)
            print(words[0].usage)
        } catch {
            print(error)
        }

        return true
    }

    ...
}

產生:

[MyApp.AppDelegate。($102bac454 的未知上下文)。($102bac58c 的未知上下文)。用法(partOfSpeech:“確定器”)]

也就是說Usage是在MyAppAppDelegate中的某個未知上下文中定義的。 簡而言之,它不知道如何表示函數內定義的類型的層次結構。

對比一下:

class AppDelegate: UIResponder, UIApplicationDelegate {

    struct WordDictionary: Codable {
        var word: String
        var usage: [Usage]
    }

    struct Usage: Codable {
        var partOfSpeech: String
    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        do {
            let url = Bundle.main.url(forResource: "test", withExtension: "json")!
            let data = try Data(contentsOf: url)
            let words = try JSONDecoder().decode([WordDictionary].self, from: data)
            print(words[0].usage)
        } catch {
            print(error)
        }

        return true
    }

    ...
}

哪個產生:

[MyApp.AppDelegate.Usage(partOfSpeech: "determiner")]


您還可以添加自己的CustomStringConvertible一致性:

struct WordDictionary: Codable {
    var word: String
    var usage: [Usage]
}

struct Usage: Codable {
    var partOfSpeech: String
}

extension Usage: CustomStringConvertible {
    var description: String { "Usage(partOfSpeech: \"\(partOfSpeech)\")" }
}

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        do {
            let url = Bundle.main.url(forResource: "test", withExtension: "json")!
            let data = try Data(contentsOf: url)
            let words = try JSONDecoder().decode([WordDictionary].self, from: data)
            print(words[0].usage)
        } catch {
            print(error)
        }

        return true
    }

    ...
}

哪個產生:

[用法(partOfSpeech:“限定詞”)]

通過CustomStringConvertible ,您可以根據需要制作print格式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM