xcode 使用JSONDecoder解码的对象的打印输出出现问题

fzsnzjdm  于 2022-12-05  发布在  其他
关注(0)|答案(2)|浏览(202)

我尝试在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函数中运行这段代码。
我不知道我错过了什么。我一直试图找到一个解决方案,现在几天,并尝试不同的方法,但仍然不能得到所需的输出,任何帮助将不胜感激。

ssm49v7z

ssm49v7z1#

医生
您的类型是在函数中定义的。请将这些类型定义移到函数之外,或者实现您自己的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是在MyApp中的AppDelegate中的某个未知上下文中定义的。简而言之,它不知道如何表示函数中定义的类型的层次结构。
与之形成对比的是:

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
    }

    ...
}

其产生:
[我的应用程序。应用程序委托。用法(部分语音:“限定词”)]
您还可以添加自己的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
    }

    ...
}

其产生:
用法(词性:“限定词”)]
通过CustomStringConvertible,您可以将print化为您想要的任何格式。

vjhs03f7

vjhs03f72#

如果希望在将一个类型的示例插入字符串时,该类型能够很好地打印出来,则需要使其符合CustomStringConvertible
此协议声明一个属性:description,当字串插补遇到符合它的对象时,它会改用description传回的字串。
您需要以下内容:

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

如果要打印类似 * 字符串的JSON。
另一种方法是使用JSONEncoder对对象进行重新编码,并将数据转换为String。这要重得多,但对于更复杂的对象可能是更好的选择。

  • JSON类,因为换行符和制表符不会被转义符替换,字符串中出现的"\也不会被转义。

相关问题