使用 Swifty 在字典中组合 JSON 和 String
Combine JSON and String in a dictionary with Swifty
我想在 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()!
}
原因
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
, which then goes through the 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")
事实证明它可以改变:
storeJson["name"] = name
至
storeJson["name"] = JSON(name)
我想在 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()!
}
原因
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
, which then goes through the 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")
事实证明它可以改变:
storeJson["name"] = name
至
storeJson["name"] = JSON(name)