"Pretty Print" json 字符串有没有比我使用的更好的方法

Is there a better way to "Pretty Print" the json string than I'm using

我有 json 数据来自服务器端。

万一我使用下一个代码,我打印的一行字符串不漂亮:

print(String(bytes: jsonData, encoding: String.Encoding.utf8))

为了让它打印得漂亮,我使用了下一个代码:

if let json = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) {
   if let prettyPrintedData = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted) {
      print(String(bytes: prettyPrintedData, encoding: String.Encoding.utf8) ?? "NIL")
   }
}

但似乎这不是最好的方法。

那么有人知道如何漂亮地打印传入的json数据来打印吗?

我想不出比本地类型更漂亮的东西了。

if let json = try? JSONSerialization.jsonObject(with: jsonData, options: []) {
    if let jsonArray = json as? [Any] { print(jsonArray) }
    else if let jsonDict = json as? [String:Any] { print(jsonDict) }
    else { print("Couldn't convert json") }
}

你所拥有的稍微漂亮一点的版本:

if let json = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers),
   let jsonData = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted) {
    print(String(decoding: jsonData, as: UTF8.self))
} else {
    print("json data malformed")
}

直接使用编码器上的输出格式选项:

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted

答案在这里。

语言:Objective-C


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。打印正文、响应等的 NSData

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

ex2。打印 NSDictionary

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

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

基本上在 Swift 中存在 2 种字符串类型:StringNSString

第二个更旧(甚至在 Objective-C 中使用),现在更经常使用较新的 String 类型。但是,NSString 允许您漂亮地打印现有字符串,这意味着 f.ex。反斜杠将被自动删除。

Json 从服务器

收到数据

对于这种情况,我使用这样的助手:

extension Data {
    var prettyString: NSString? {
        return NSString(data: self, encoding: String.Encoding.utf8.rawValue) ?? nil
    }
}

在 String 类型上使用 NSString 非常重要。

或者,您可以对 String 进行操作,但最后将其转换为 AnyObject,如下所示:

String(data: stringData, encoding: .utf8)! as AnyObject

控制台中的结果如下所示(服务器响应示例):

{
  "message" : "User could not log in",
  "errorCode" : "USER_COULD_NOT_LOG_IN",
  "parameters" : null
}

现有字符串的漂亮字符串

要美化任何字符串,您可以使用上面的第二种方法,因此将 String 转换为 AnyObject。它还将使字符串看起来更好。 F.ex.:

let myStr: String = ...
print(myStr as AnyObject)

数据扩展名:

extension Data {
    
    func printFormatedJSON() {
        if let json = try? JSONSerialization.jsonObject(with: self, options: .mutableContainers),
           let jsonData = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted) {
            pringJSONData(jsonData)
        } else {
            assertionFailure("Malformed JSON")
        }
    }
    
    func printJSON() {
        pringJSONData(self)
    }
    
    private func pringJSONData(_ data: Data) {
        print(String(decoding: data, as: UTF8.self))
    }
}

用法:

data.printFormatedJSON()

Swift 5岁以上

方便的数据扩展 pretty-print JSON

extension Data {
    
    func toPrettyJSON() {
        do {
            let json = try JSONSerialization.jsonObject(with: self, options: [])
            let data = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
            guard let jsonString = String(data: data, encoding: .utf8) else {
                print("Inavlid data")
                return
            }
            print(jsonString)
        } catch {
            print("Error: \(error.localizedDescription)")
        }
    }
}

如何使用:

 let json = """
  {
    "id": 1,
    "name": "Steve Jobs",
    "username": "Steve",
    "email": "jobs@apple.com",
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "San Jose",
      "zipcode": "1234-5678"
    },
    "phone": "1-770-736-8031 x56442"
  }
"""

let jsonData = Data(json.utf8)
// log json data in pretty format
jsonData.toPrettyJSON()