SwiftyJSON - 无法从 JSON 字符串获取 transactionId
Posted
技术标签:
【中文标题】SwiftyJSON - 无法从 JSON 字符串获取 transactionId【英文标题】:SwiftyJSON - Unable to get transactionId from JSON String 【发布时间】:2019-08-28 19:27:47 【问题描述】:我正在使用 CocoaAsyncSocket 从使用 JSON 的服务器 API 检索消息。我能够获取数据并将其转换为可打印的字符串,但我无法使用 SwiftyJSON 从尝试解析我已经拥有的 JSON 字符串中检索一个值 (transactionId
)。我知道还有其他类似的帖子,但都没有解决我的问题。
在 ViewController 中:
func socket(_ sock: GCDAsyncSocket, didRead data: Data, withTag tag: Int)
guard let msg = String(data: data, encoding: .utf8) else return
var response = " "
if msg.contains("Reset")
transactionID = ParseJSON().parse(message: msg)
response = String(format: "\"Response\":\"transactionId\":\"%@%\",\"content\":\"Reset\":", transactionID)
socket.write((response.data(using: .utf8))!, withTimeout: -1, tag: 0)
socket?.readData(withTimeout: -1, tag: 0)
ParseJSON 类:
func parse (message: String) -> String
var parsedMessage = " "
let json = JSON(parseJSON: message)
let transactionId = json["Request"]["transactionId"].stringValue
parsedMessage = transactionId
print(parsedMessage)
return parsedMessage
显示的结果是一个空的 transactionId 值。没有打印或任何东西。 如果您在我的代码中发现任何错误或有更好的方法,请告诉我!
编辑:
这是我要解析的字符串:
“请求”:“内容”:“重置”:,“transactionId”:“f7c4d630-552b-46d9-a37d-44450537b48d”
这是我的输出:
\"Response\":\"transactionId\":\"\",\"content\":\"Reset\":
【问题讨论】:
可能不相关,但transactionId
占位符中的尾随 %
是有意的吗?
那是无意的,它并没有解决我的问题,但我肯定会删除它,以防它导致进一步的问题。
肯定有其他事情发生,因为上面的工作正常:gist.github.com/robertmryan/3f181810c17bba9eb982073f4983d815 当然,你可以简化一下parse
,你可以去掉那个无关紧要的%
,我不会建议手动构建 JSON 等,但最重要的是,以上工作正常。还有一些其他问题(例如,msg
不能与您描述的完全一样,等等)。\
所以这是我从你提供的内容中发现的,如果我像你一样使用与 msg 相同的字符串创建一个变量,那么它就可以工作。没有意义的是为什么我可以从打印的 msg 中复制并从中创建一个有效的变量,但是如果我使用变量 msg 本身,则什么都不会被解析。
【参考方案1】:
问题不在于代码。考虑:
func parse(message: String) -> String
let json = JSON(parseJSON: message)
return json["Request"]["transactionId"].stringValue
let input = """
"Request": "content": "Reset": , "transactionId": "f7c4d630-552b-46d9-a37d-44450537b48d"
"""
let transactionID = parse(message: input)
print("transactionId:", transactionID)
let response = String(format: "\"Response\":\"transactionId\":\"%@\",\"content\":\"Reset\":", transactionID)
print("response:", response)
如您所料,上述结果是:
transactionId:f7c4d630-552b-46d9-a37d-44450537b48d
响应:"Response":"transactionId":"f7c4d630-552b-46d9-a37d-44450537b48d","content":"Reset":
所以我怀疑输入 message
与您的预期不太一样。所以我可能会建议添加一些错误处理,以便您可以准确诊断出问题所在:
func parse(message: String) -> String
let json = JSON(parseJSON: message)
if let error = json.error
fatalError("JSON parsing error: \(error)")
let request = json["Request"]
if let error = request.error
fatalError("request error: \(error)")
let transactionId = request["transactionId"]
if let error = transactionId.error
fatalError("transactionId error: \(error)")
return transactionId.stringValue
现在,在实践中,您可能不会使用fatalError
,而是会进行一些优雅的错误处理(例如,将parse
更改为throws
,然后throw
遇到的错误,如果有的话,然后catch
调用parse
的错误并优雅地处理任何运行时问题)。但在此诊断过程中,fatalError
很有用,因为它会在有问题的行停止调试器,从而简化诊断过程。
归根结底,请求不能完全符合您的期望。请注意,它将对大小写、格式错误的 JSON 等非常敏感。因此,通过查看 SwiftyJSON 提供的错误,您应该能够很快缩小问题范围。
下面,你告诉我们Data
是:
<7b225265 71756573 74223a20 7b22636f 6e74656e 74223a20 7b225265 73657422
3a207b7d 7d2c2022 7472616e 73616374 696f6e49 64223a20 22643937 36303036
622d3130 38302d34 3864652d 39323232 2d623139 63363663 35303164 31227d7d
00>
问题在于最后一个字节0x00
。如果你删除它,它会起作用。
FWIW,当我将该十六进制字符串转换回 Data
并通过 JSONSerialization
运行时,它确认了诊断:
错误域=NSCocoaErrorDomain Code=3840 "最后的垃圾。" UserInfo=NSDebugDescription=垃圾结束。
您需要弄清楚为什么 0x00
包含在有效负载的末尾并将其删除。
【讨论】:
使用您提供的错误处理,我收到了这个致命错误:Thread 1: Fatal error: Request error: wrongType。这个 wrongType 错误意味着 JSON 在顶层的类型不同 ,我不确定这是什么意思。 您在哪一行收到该错误?无论如何,它证实了 JSON 与您描述的不同的假设。最有可能的是,它只是格式不正确。也许您在某处遗漏了引号。也许"
是”
。可能有些牙套不平衡。很难说。我们需要查看实际的 JSON,这显然不是您在问题中提供的。它可能看起来相似,但并不完全相同。 (顺便说一句,这就是为什么我们不像您的 String(format:)
示例那样手动构建 JSON 字符串的原因,正是为了避免此类问题。)
我现在正在临时手动构建 JSON 字符串,但这不是我要解析的内容。我提供的 JSON 是从中继服务器读取的,我没有手动构建或格式化它。我打印了中继服务器发送的内容并将其从日志中复制到此处。中继服务器目前正在读取我的格式化字符串,但我最终尝试从中继服务器读取并没有按预期进行。我提供的内容是直接从guard let msg = String(data: data, encoding: .utf8) else return
打印的日志中复制的
既然它不是那么大,你为什么不print(data as NSData)
和我们分享那个完整的十六进制字符串......
<7b225265 71756573 74223a20 7b22636f 6e74656e 74223a20 7b225265 73657422 3a207b7d 7d2c2022 7472616e 73616374 696f6e49 64223a20 22643937 36303036 622d3130 38302d34 3864652d 39323232 2d623139 63363663 35303164 31227d7d 00>
每个字符串唯一不同的是transactionId
不同,此外这应该与我之前提供的准确无误。以上是关于SwiftyJSON - 无法从 JSON 字符串获取 transactionId的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 SwiftyJSON 从深度嵌套的 JSON 字典中获取字符串 [重复]