【问题标题】:How to prettyPrint json response from API call in debugger?如何在调试器中从 API 调用中漂亮地打印 json 响应?
【发布时间】:2018-07-30 05:00:36
【问题描述】:

在调试时试图弄清楚如何从 API 中漂亮地打印我的响应的 json 值:

let session = URLSession(configuration: .default)
let task = session.dataTask(with: urlRequest) { data, response, error in
    completion(data, response, error)
}

在调试器中,如果我做 po 数据,我会得到这样的结果:

如何打印出数据对象中的实际 json 结构?希望看到这样的东西:

{ "firstName" : "约翰", "lastName" : "Doe", ... }

po debugPrint(data) 在这种情况下不输出任何内容。

【问题讨论】:

  • @Alexander 你读过这个问题吗?它与您的“重复”完全无关,除此之外它也与 JSON 有关。一个问题是关于如何输出 JSON 进行调试,另一个是关于解析 JSON 数据的问题。 不是重复的。
  • @dr_barto output JSON for debugging 不,不是。 OP 有一个 Data 的实例,其中包含 jason 编码的文本(显示的字节为 UTF8 表示 {"mes),尚未解析。为了让 OP 获得他正在寻找的漂亮打印的调试输出,他需要先解析它。
  • @Alexander 是的,这不是重复的。链接的答案没有回答我关于调试时如何获取 json 的问题...
  • 正确答案是po String(decoding: response.data!, as: UTF8.self)
  • 我通过谷歌找到了这个。它绝对不是重复的。问题在于能够在调试器中检查 API 调用的响应,而无需为此修改代码。最好的方法是在 Xcode 调试器中右键单击本地的 data 变量,然后单击 Add Expression... 然后您可以输入此表达式 String(data: data, encoding: .utf8) 它将在调试器中创建一个新的字符串变量(而不是在您的source),它可以让您从响应中读取原始数据。

标签: swift xcode debugging xcode9


【解决方案1】:

试试JSONSerialization,类似这样:

let url = URL(string: "http://date.jsontest.com")
var request : URLRequest = URLRequest(url: url!)
request.httpMethod = "GET"

let dataTask = URLSession.shared.dataTask(with: request) {
    data,response,error in
    do {
        if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
            print(jsonResult)
        }
    } catch let error {
        print(error.localizedDescription)
    }
}
dataTask.resume()

jsonResult 会在哪里打印出来:

{
    date = "02-19-2018";
    "milliseconds_since_epoch" = 1519078643223;
    time = "10:17:23 PM";
}

【讨论】:

  • JSONSerialization 有点过时了。您应该尽可能使用 codable(例如这种情况)。
  • 如何在调试器中执行此操作?
  • JSONSerialization 更适合这种情况。您不能在此处使用JSONDecoder,因为响应是动态的。
  • 不幸的是,这可能会打印出误导性信息 - 例如浮动精度不高
【解决方案2】:
// given raw JSON, return a usable Foundation object
private func convertDataWithCompletionHandler(_ data: Data, completionHandlerForConvertData: (_ result: AnyObject?, _ error: NSError?) -> Void) {
    
    var parsedResult: AnyObject! = nil
    do {
        parsedResult = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as AnyObject
    } catch {
        let userInfo = [NSLocalizedDescriptionKey : "Could not parse the data as JSON: '\(data)'"]
        completionHandlerForConvertData(nil, NSError(domain: "convertDataWithCompletionHandler", code: 1, userInfo: userInfo))
    }
    completionHandlerForConvertData(parsedResult, nil)
}

【讨论】:

  • JSONSerialization 有点过时了。您应该尽可能使用 codable(例如这种情况)。
  • 如何在调试控制台中执行此操作?
  • @Prabhu 你所拥有的只是Data。您可以将其转换为字符串,但您获得的 JSON 不一定打印得很漂亮,因此无法满足您的要求。为此,首先打开您的数据,然后将其传递给String.init(data:encoding:)。您可以使用Optional.map: po data.map { String(data: $0, encoding: .utf8) } 一次性完成。
  • @Prabhu 要获得实际打印的漂亮数据,或此 JSON 的其他一些可管理形式,您需要先解析它,就像重复问题显示的那样。
  • @Alexander 所以调试器中没有命令可以用来实际查看后端发送给我的实际 json 对象?知道为什么 xcode 没有这个简单的功能吗?其他编辑器,如 Visual Studio for C#,似乎没有显示 json 的问题....
【解决方案3】:
e print(String(data: JSONSerialization.data(withJSONObject: JSONSerialization.jsonObject(with: data, options: []), options: .prettyPrinted), encoding: .utf8)!)

【讨论】:

    【解决方案4】:

    这是给你的 Objective-c 代码。你可以翻译一下。

    类别(objc) -> 扩展名(swift)

    NSLog(objc) -> 打印(swift)

    类似这样的。


    NSString+PrettyPrint.h

    @interface NSString (PrettyPrint)
    
    + (NSString * _Nonnull)prettifiedJsonStringFromData:(nullable NSData *)data;
    + (NSString * _Nonnull)prettifiedStringFromDictionary:(nullable NSDictionary *)dictionary;
    
    @end
    

    NSString+PrettyPrint.m

    #import "NSString+PrettyPrint.h"
    
    @implementation NSString (PrettyPrint)
    
    + (NSString *)prettifiedStringFromDictionary:(nullable NSDictionary *)dictionary {
        
        if (dictionary == nil) { return @"nil"; }
        
        NSMutableString *returnStr = [NSMutableString stringWithString:@"[ \n"];
        
        for (NSString *key in dictionary) {
            [returnStr appendFormat:@"  %@: %@,\n", key, [dictionary valueForKey:key]];
        }
    
        [returnStr appendFormat:@"]"];
    
        return returnStr;
    }
    
    + (NSString *)prettifiedJsonStringFromData:(nullable NSData *)data {
        
        if (data == nil) { return @"nil"; }
        
        NSData *jsonData;
        NSError *error = nil;
        
        NSString *jsonStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        jsonData = [jsonStr dataUsingEncoding:NSUTF8StringEncoding];
        id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:&error];
        if (jsonObject == nil) {
            return @"nil (json object from data)";
        } else {
            BOOL isValidJsonObject = [NSJSONSerialization isValidJSONObject:jsonObject];
            if (isValidJsonObject) {
                NSData *finalData = [NSJSONSerialization dataWithJSONObject:jsonObject options:NSJSONWritingPrettyPrinted error:&error];
                //TODO: error description
                NSString *prettyJson = [[NSString alloc] initWithData:finalData encoding:NSUTF8StringEncoding];
                return prettyJson;
            } else {
                return [NSString stringWithFormat:@"%@\n%@", jsonStr, @" (⚠️ Invalid json object ⚠️)\n"];
            }
        }
    }
    
    @end
    

    然后在你需要使用方法时调用它们。

    ex1.为 body、response ...等打印 NSData

    NSLog(@"body: %@", [NSString prettifiedJsonStringFromData:[request HTTPBody]]);
    

    ex2.打印 NSDictionary

    NSLog(@"headers: %@", [NSString prettifiedStringFromDictionary:[request allHTTPHeaderFields]]);
    

    您可能会在日志中得到这些结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-26
      • 2013-10-03
      • 2011-08-05
      相关资源
      最近更新 更多