IOS 中json解析异常Domain=NSCocoaErrorDomain Code=3840之诡异事件

前言

就在今天遇到一个很诡异的技术问题,Unity调用Quick苹果SDK支付。Quick 支付需要游戏(Unity)传入一些数据到原生OC中,格式是json,在OC中打印的日志看着数据是没问题的,但是解析json却一直显示失败 。问题最终还是解决了,用倒推法给大家说一下解决的思路。

1.jpg

场景重现

下面代码是OC中定义的支付方法,void *payData是接Unity中传过来的支付json数据,当用户点击支付按钮的时候,Unity把支付的数据传到IOS 原生OC中。没有了解过的可以看下之前写过的文章 :Unity接入ios SDK(小7手游)没有你想的那么难

//支付
void SDk_pay(void *payData){
       NSLog(@"SDk_pay"); //控制台展示这段日志说明Unity调用到了OC的支付方法

       NSString *idList = [NSString stringWithUTF8String:payData];
       NSLog(@"获取的支付数据=======:%@",idList);

       //将解析得到的内容存放字典中,编码格式为UTF8,防止取值的时候发生乱码

       NSData *jsonData = [idList dataUsingEncoding:NSUTF8StringEncoding];
       NSError *err;
       NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
                                               options:NSJSONReadingMutableContainers error:&err];
       
       if(err) {
           NSLog(@"json解析失败:%@",err);
           return;
       }
}

当点击完成支付按钮后,控制台显示Json解析异常日志如下所示:

json解析失败:Error Domain=NSCocoaErrorDomain Code=3840 "Unescaped control character around character 206." 
UserInfo={NSDebugDescription=Unescaped control character around character 206.}

解决问题思路和过程

上面解析Json异常去Google 上去搜了一下,根据搜索内容的解释,出现这个问题的原因就是:返回的Json字符串里面有换行符、空格。既然知道是什么原因导致的,那么我们一步步分析一下。

NSLog(@“SDk_pay”);控制台有这么一段日志,说明Unity调用OC的支付方法是没问题的,成功调用到了。再看下一个日志点,获取Unity传过来的数据 idList ,传过来的数据字段如下代码:

payLog.png

看着上面显示的日志乍一看返回的数据都是正常,没有什么特殊啊?但是异常报错不会错的。于是把我上面的Json数据放到了格式化工具上查看,果然发现了问题所在。Json中 orderid字段多一个空格(截图中小红点就是一个空格)。

formatJson.png

既然知道是订单号的问题,我们来倒推一下,订单号(orderid字段)是拼的加密字符串由游戏服务器原样返回,其中一部分数据取自客户端的ChannelId。我把代码贴出来乍一看还是没问题吧。

method.png

其实所有问题的关键都指向了return MakeStringCopy(“10184”)这货。最开始我定位到GetSdkChannelId()方法里了,但是怎么看怎么也不像有空格的样子啊?于是我尝试用光标一点点试看有没有空格,一试果然试出问题了。

下面截图就是我从有问题的那段注释里copy出来放到VSCode里面,一看10184后面已有一个空格的。当时我都惊了,同一个字符串在Xcode里面显示的正常,在VSCode里面却多出一个空格。

Xcode(11.5版本)还有这个操作? 由于我不是专业搞IOS的,我查了资料还有询问了一些写IOS的朋友。最终结论基本上都是Xcode编译器自带的Bug。把空格去掉继续跑程序,一点事都没有。事情就这样解决了,你学废了吗?

There is a problem.png

结尾

如果文章对你有帮助留下一个赞呗,你的支持是我继续写下去的动力,如有不对劳烦大家多多指正。

在使用ARKit (iOS) 开发环境中,如果你需要通过HTTP请求获取JSON数据并将其解析成类实例,通常会涉及到网络请求库(如Alamofire、URLSession等)以及JSON解析库(如SwiftyJSON、 ObjectMapper 或 Codable)。以下是基本步骤: 1. **导入必要的库**: 首先,确保在项目中导入相关的网络请求库和JSON解析库。例如,如果你选择使用Swift标准库中的Codable,你需要导入`Foundation`框架。 ```swift import Foundation ``` 2. **创建HTTP请求**: 使用`URLSession`发起GET或POST请求,并配置相应的URL、头信息和完成处理函数。 ```swift func fetchData(from url: URL, completion: @escaping(Result<Data, Error>) -> Void) { let task = URLSession.shared.dataTask(with: url) { data, response, error in // 处理响应和错误 if let error = error { completion(.failure(error)) } else if let data = data { completion(.success(data)) } } task.resume() } ``` 3. **解析JSON数据**: 使用Codable协议将收到的数据转换为自定义模型类的实例。首先,创建一个模型类,例如`YourDataModel`, 它应该和JSON结构相对应。 ```swift struct YourDataModel: Codable { var property1: String var property2: Int // 其他属性... } let decoder = JSONDecoder() // 解析数据 func parseJson(_ data: Data, completion: @escaping(YourDataModel?, Error?) -> Void) { do { if let decodedData = try decoder.decode(YourDataModel.self, from: data) { completion(decodedData, nil) } else { completion(nil, NSError(domain: "DecodingError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to decode JSON"])) } } catch { completion(nil, error) } } ``` 4. **整合请求与解析**: 调用`fetchData`方法获取数据后,立即解析它。 ```swift fetchData(from: someUrl) { result in switch result { case .success(let data): parseJson(data) { model, error in if let model = model { // 使用model实例 } if let error = error { print("JSON parsing error: \(error.localizedDescription)") } } case .failure(let error): print("Error fetching data: \(error.localizedDescription)") } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值