无法快速从 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 字符串格式不正确,则无法提取所有值

如何从 JSON 中获取整数

Rest Template 无法正确解析 json rest api 响应

无法从 React Native 中的 JSON 数组正确获取数据

使用 Python 从 Twitter 流 API 中提取特定的 JSON 字段

提取json对象中的数据,转化为数组