如何将 Optional<Any> 破译成字典数组?

Posted

技术标签:

【中文标题】如何将 Optional<Any> 破译成字典数组?【英文标题】:How do I decipher Optional<Any> into an Array of Dictionaries? 【发布时间】:2017-01-27 07:24:10 【问题描述】:

以下是 abridge JSON 数据列表:

let json = JSON(data: response.result.value!).dictionary
self?.processData(json: json!)
...
...
func processData(json:[String:Any]) 
        let myList = json["list"]
...

--------------------------------------------------------------------- 
(lldb) po myList
▿ Optional<Any>
  ▿ some : [
  
    "author" : "Jimmy Kickarse",
    "word" : "Turkey",
    "defid" : 1925960,
    "current_vote" : "",
    "thumbs_down" : 1103,
    "thumbs_up" : 1987,
    "permalink" : "http:\/\/turkey.urbanup.com\/1925960",
    "example" : "If through some crazy events Asia and Europe went to war, they'd both bomb Turkey.",
    "definition" : "A country that's incredibly fun to be in because it's not quite European, but not quite Asian either."
  ,
  …
  
    "author" : "DildoBob",
    "word" : "Turkey",
    "defid" : 7671084,
    "current_vote" : "",
    "thumbs_down" : 27,
    "thumbs_up" : 112,
    "permalink" : "http:\/\/turkey.urbanup.com\/7671084",
    "example" : "Turkey cannot tweet, because Prime Minister Recep Tayyip Erdogan (Or if you are dyslexic, Pro Gay Centipede Ray) banned it's usage and access.",
    "definition" : "A bird that can't tweet."
  
]

    ▿ rawArray : 10 elements
      ▿ 0 : 9 elements
        ▿ 0 : 2 elements
          - .0 : author
          - .1 : Jimmy Kickarse
        ▿ 1 : 2 elements
          - .0 : word
          - .1 : Turkey
        ▿ 2 : 2 elements
          - .0 : defid
          - .1 : 1925960
        ▿ 3 : 2 elements
          - .0 : current_vote
          - .1 : 
        ▿ 4 : 2 elements
          - .0 : thumbs_down
          - .1 : 1103
        ▿ 5 : 2 elements
          - .0 : thumbs_up
          - .1 : 1987
        ▿ 6 : 2 elements
          - .0 : permalink
          - .1 : http://turkey.urbanup.com/1925960
        ▿ 7 : 2 elements
          - .0 : example
          - .1 : If through some crazy events Asia and Europe went to war, they'd both bomb Turkey.
        ▿ 8 : 2 elements
          - .0 : definition
          - .1 : A country that's incredibly fun to be in because it's not quite European, but not quite Asian either.
…
…      
    - rawDictionary : 0 elements
    - rawString : ""
    - rawBool : false
    - _type : SwiftyJSON.Type.array
    - _error : nil


我怎样才能破译这个? 该列表显示它是一个“SwiftJSON.Type.array”(见上文)。 但下面说它不是:
(lldb) po type(of:myList)
Swift.Optional<Any>

它看起来像一个字典数组。 所以我试图把它改成这样:

(lldb) po myList as [[String:String]]
error: Execution was interrupted, reason: signal SIGABRT.
The process has been returned to the state before expression evaluation.

怎么才能得到这个对象的元素?? ...或正确地将其转换为要破译的字符串字典数组?


跟进:
if let myList = json["list"] as? [[String:Any]] 
            print("Do Something")

'if' 语句失败。

【问题讨论】:

【参考方案1】:

您的myList 肯定是字典数组,但您需要将其转换为[[String:Any]] 而不是[[String:String]],因为它的Dictionary 包含numberstring 都作为一个值,所以只需将其转换为@ 987654327@ 为您工作。

if let myList = json["list"] as? [[String:Any]] 
    //access your myList array here

【讨论】:

我破译了“myList”并得到以下信息:(lldb) po myList 表达式产生错误:错误:执行被中断,原因:EXC_BAD_ACCESS (code=EXC_I386_GPFLT)。进程已经返回到表达式求值前的状态。 @FrederickC.Lee 你可以简单地打印json 并在此处添加控制台输出 @FrederickC.Lee 你还没有回复,现在可以了吗? 我做了一个 print() 并从那里开始工作。显然这有效....我希望通过调试器有一种比使用 print() 更直接的方法。【参考方案2】:

根据建议,我将数据打印出来:

func getData(str:String) 
        Alamofire.request(MashapeRouter.getDefinition(str))
            .responseData  response in
                let json = JSON(data: response.result.value!).dictionary
                print("\n-------------\n")
                print(json!)
                return;
        

我得到以下信息:

 -------------

["result_type": exact, "sounds": [
  "http:\/\/media.urbandictionary.com\/sound\/turkey-7377.mp3",
  "http:\/\/wav.urbandictionary.com\/turkey-21188.wav",
  "http:\/\/wav.urbandictionary.com\/turkey-24905.wav",
  "http:\/\/wav.urbandictionary.com\/turkey-40301.wav"
], "list": [
  
    "example" : "If through some crazy events Asia and Europe went to war, they'd both bomb Turkey.",
    "thumbs_down" : 1103,
    "author" : "Jimmy Kickarse",
    "defid" : 1925960,
    "definition" : "A country that's incredibly fun to be in because it's not quite European, but not quite Asian either.",
    "thumbs_up" : 1988,
    "word" : "Turkey",
    "permalink" : "http:\/\/turkey.urbanup.com\/1925960",
    "current_vote" : ""
  ,
  
    "example" : "That honkey is one straight-up jive turkey!",
    "thumbs_down" : 686,
    "author" : "Jam Master J",
    "defid" : 1528701,
    "definition" : "(n) a loser; an uncoordinated, inept, clumsy fool\r\nOR\r\na tool; a person who is not in with current culture and slang or is just generally uncool. \r\nThese slang usages of the word \"turkey\" were mostly used during the late 60's and 70's by urban-dwelling blacks.\r\nSee [jive turkey]",
    "thumbs_up" : 1160,
    "word" : "turkey",
    "permalink" : "http:\/\/turkey.urbanup.com\/1528701",
    "current_vote" : ""
  ,…
], 

"tags": [
  "thanksgiving",
  "chicken",
  "sex",
  "turkish",
  "turk",
  "food",
  "gobble",
  "duck",
  "ham",
  "sandwich"
]]

基于此输出,我尝试了以下操作:

po json!["list"]?[0]["example"].string! 
▿ Optional<String>
  - some : "If through some crazy events Asia and Europe went to war, they\'d both bomb Turkey."

所以我接近了:

  if let myString = json!["list"]?[0]["example"].string 
                    print("myString= \(myString)")
                

...我从中得到以下信息:

myString= If through some crazy events Asia and Europe went to war, they'd both bomb Turkey.
(lldb) 

...所以显然我需要做的就是把这一切清理干净;避免“末日金字塔”:- 多个可选展开

【讨论】:

以上是关于如何将 Optional<Any> 破译成字典数组?的主要内容,如果未能解决你的问题,请参考以下文章

带有 std::any 和 std::optional 的 any_cast

如何将 Optional<T> 转换为 Stream<T>?

非可选的展开值

如何将空 JSON 数据推送到 Observable<any[]> angular 2 类型的数组字段

orElseGet 在 Optional<List<Entity>> 的情况下如何工作

如何将boost :: any打印到流中?