【问题标题】:Combine JSON and String in a dictionary with Swifty使用 Swifty 在字典中组合 JSON 和 String
【发布时间】:2016-02-14 13:20:11
【问题描述】:

我想在 Swifty 中创建一个 JSON 对象,格式如下:

{
    "store": {
        "id": {
            "test": "test"
        },
        "type": "retail",
        "name": "store1"

    }
}

有没有办法将字典中的类型与 Swifty(字符串和 JSON)一起使用?引号有效,但是当我尝试分配变量时,它会抱怨:Cannot assign value of type 'String' to type 'JSON?':

func jsonTest()->String {
    var storeJson = [String: JSON]()
    var someJson = JSON(["test":"test"])
    storeJson["id"] = someJson
    storeJson["type"] = "retail" // <-- works fine
    var name = "store1"
    storeJson["name"] = name // <-- Doesn't work
    var store = JSON(storeJson)
    return store.rawString()!
}

【问题讨论】:

    标签: json swift dictionary swifty-json


    【解决方案1】:

    原因

    storeJson["type"] = "retail"
    

    工作方式不同于

    storeJson["name"] = name
    

    是因为第一个在代码中遵循不同的路径。具体来说,它在以下扩展(source)中使用了init(stringLiteral value: StringLiteralType) 方法。

    extension JSON: Swift.StringLiteralConvertible {
    
        public init(stringLiteral value: StringLiteralType) {
            self.init(value)
        }
    
        public init(extendedGraphemeClusterLiteral value: StringLiteralType) {
            self.init(value)
        }
    
        public init(unicodeScalarLiteral value: StringLiteralType) {
            self.init(value)
        }
    }
    

    在我们讨论如何解决您的具体问题后,我会进一步解释。

    可能的解决方案#1

    storeJson["name"]?.string = name
    

    输出:

    {
      "id" : {
        "test" : "test"
      },
      "type" : "retail"
    }
    

    原因

    storeJson["name"]?.string = name
    

    不像我们想象的那样工作是因为可选链接。现在,如果我们通过调试器运行它,我们将看不到任何有意义的东西。事实上,我们会看到什么都没有。这有点令人担忧,可能意味着storeJson["name"]nil,因此该语句不再执行。让我们通过爆炸来验证我们的假设。我们将这一行改为:

    storeJson["name"]!.string = name
    

    在这种情况下,使用您当前的代码,您可能会得到

    fatal error: unexpectedly found nil while unwrapping an Optional value
    

    你应该这样做,因为storeJson["name"] 实际上是nil。因此,此解决方案不起作用

    可能的解决方案#2:

    正如您在回答中正确指出的那样,如果您添加 storeJson["name"] = JSON(name),您将获得所需的行为:

    func jsonTest()->String {
        var storeJson = [String: JSON]()
        var someJson = JSON(["test":"test"])
        storeJson["id"] = someJson
        storeJson["type"] = "retail" // <-- works fine
        var name = "store1"
        storeJson["name"] = JSON(name) // <-- works!
        var store = JSON(storeJson)
        return store.rawString()!
    }
    

    输出:

    {
      "id" : {
        "test" : "test"
      },
      "name" : "store1",
      "type" : "retail"
    }
    

    太棒了!因此,此解决方案有效!现在,稍后在您的代码中,您可以使用 .string 等随意更改它。

    说明

    回到字符串字面量的工作原理。你会在init 中注意到,它有

    self.init(value)
    

    通过对象init,然后通过case statement

            ...
            case let string as String:
                _type = .String
                self.rawString = string
            ...
    

    当您拨打storeJson["name"] = JSON(name) 时,您将跳过StringLiteralType init 而直接进入switch

    因此,你可以互换

    storeJson["type"] = "retail"
    

    storeJson["type"] = JSON("retail")
    

    【讨论】:

    【解决方案2】:

    事实证明它可以改变:

    storeJson["name"] = name

    storeJson["name"] = JSON(name)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-08
      • 1970-01-01
      • 2019-01-31
      相关资源
      最近更新 更多