无法快速从 JSON 中正确提取数据
Posted
技术标签:
【中文标题】无法快速从 JSON 中正确提取数据【英文标题】:Unable to extract data properly from JSON in swift 【发布时间】:2019-07-11 09:15:20 【问题描述】:将json字符串解析为对象后,我的响应中有一个这种json对象
[
"requestId": 1,
"response":
code = SUCCESS;
,
"messageId": ACTION_COMPLETE
]
我正在尝试使用
提取requestId
responseMsg["requestId"] as! Int
我收到这个错误
无法将“NSTaggedPointerString”(0x21877a910) 类型的值转换为 'NSNumber' (0x218788588)。
我试过改成Int(responseMsg["requestId"] as! String)!
这东西适用于正数,但不适用于负数,当requestId = -2
它给我一个错误时可能 bcz
无法将“__NSCFNumber”(0x21877a000) 类型的值转换为 'NSString' (0x218788290)。
我也尝试了不同的其他解决方案,但没有奏效。
【问题讨论】:
json 是返回"1"
还是只返回 1
JSON 是数组还是字典?
该 json 与 swift log @CerlinBoss 中出现的完全相同
json 表示在 swift @PGDev 中很混乱
您的回复是否总是有相同的数据?如果是,请使用decodable stuct
【参考方案1】:
为了解析 JSON 数据,最好使用 Codable
而不是手动解析所有内容。
对于JSON格式,
"requestId": 1,
"response":
"code":"SUCCESS"
,
"messageId": "ACTION_COMPLETE"
创建模型,例如,
struct Root: Decodable
let requestId: String?
let messageId: String
let response: Response
enum CodingKeys: String, CodingKey
case requestId, messageId, response
init(from decoder: Decoder) throws
let values = try decoder.container(keyedBy: CodingKeys.self)
if let id = try? values.decode(Int.self, forKey: .requestId)
requestId = String(id)
else if let id = try? values.decode(String.self, forKey: .requestId)
requestId = id
else
requestId = nil
messageId = try values.decode(String.self, forKey: .messageId)
response = try values.decode(Response.self, forKey: .response)
现在,解析 JSON 数据 使用,
do
let root = try JSONDecoder().decode(Root.self, from: data)
print(root.requestId) //access requestId like this....
catch
print(error)
【讨论】:
如果requestId
类型发生变化,那么这将导致解码错误
我的响应会像这样 struct Response: Decodable let code: String, let data : [String : Any] 。但它显示错误
@Sh_Khan 如果JSON响应是这样的,为什么类型会改变,
类型“响应”不符合协议“可解码”
以上是控制台日志,不是json结构,所以无法知道requestId
的类型【参考方案2】:
试试
Int(String(describing: responseMsg["requestId"]))!
这确保任何数据都先转换为字符串,然后再转换为 int
【讨论】:
字符串类型转换为 nil【参考方案3】:这个错误信息
Could not cast value of type 'NSTaggedPointerString' (0x21877a910) to 'NSNumber' (0x218788588).
告诉我们 JSON 请求 id 被解析为字符串。 NSTaggedPointerString
是 ObjC 运行时用来表示字符串的特殊内部类型。
试试这个:
let requestId = responseMsg["requestId"] as! String
print("request id: \(requestId)") // Prints a string
注意,它可能会打印一些看起来像数字的东西,但它不是数字。
您正在解析的 JSON 可能看起来像
"requestId": "1",
"response":
"code" = "SUCCESS"
,
"messageId": "ACTION_COMPLETE"
注意引号中的1
。
【讨论】:
【参考方案4】:斯威夫特 5
字符串插值对我有用! (首先将其转换为 String
不起作用,因为我有其他值,json 解码器 实际上 完成了它的工作并将它们直接转换为一个数字)
if let responseMsg_any = responseMsg["requestId"],
let responseMsg_int = Int("\(responseMsg_any)")
//..
警告:
此解决方案允许任何 Type
成为String
并检查Int
值。仅当您在插值之前不关心值的 Type
时才使用此选项。
【讨论】:
以上是关于无法快速从 JSON 中正确提取数据的主要内容,如果未能解决你的问题,请参考以下文章
BigQuery json 函数 - 如果 json 字符串格式不正确,则无法提取所有值
Rest Template 无法正确解析 json rest api 响应
无法从 React Native 中的 JSON 数组正确获取数据