【问题标题】:Is there a better way to "Pretty Print" the json string than I'm using有没有比我使用的更好的方法来“漂亮打印”json字符串
【发布时间】:2018-10-11 01:29:24
【问题描述】:

我有 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")
   }
}

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

那么有人知道如何漂亮地打印传入的 jsonData 来打印它吗?

【问题讨论】:

  • “但似乎这不是最好的方法。”到底有什么问题?
  • @Alexander,错误的是,此代码将 jsonData 转换为 jsonObject,而不是将 jsonObject 转换为 jsonData。这就像一项需要做两次的工作。
  • jsonData 最初来自哪里?在你需要打印的地方,你有它生成的源对象吗?
  • @Alexander,我使用 Alamofire 发送请求。响应包含 json 数据。所以我想在应用收到响应后立即打印它
  • 漂亮的打印需要在所有正确的位置放置空白。确定所有正确的位置与反序列化 JSON 几乎相同,唯一的区别是您不需要解释解析的字段来构建对象图。但这不会花费太多时间,因此编写一个单独的 JSON 解析器来解析字符串只是为了漂亮打印是很愚蠢的

标签: json swift pretty-print


【解决方案1】:

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

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")
}

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 这只有在你方进行编码时才有效。从他的其他 cmets 那里,他从服务器获取了一些东西,所以他没有那个选项。
    • 虽然这可能会回答另一个问题,但这完全解决了我搜索的问题。
    【解决方案3】:

    在 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
        }
    }
    

    在字符串类型上使用 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。它还将使字符串看起来更好。例如:

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

    【讨论】:

      【解决方案4】:

      数据扩展:

      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()
      

      【讨论】:

        【解决方案5】:

        这就是答案。

        语言: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.为 body、response ...等打印 NSData

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

        ex2.打印 NSDictionary

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

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

        【讨论】:

          【解决方案6】:

          我想不出比原生类型更漂亮的东西了。

          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") }
          }
          

          【讨论】:

          • 我认为问题的目标是获得漂亮的打印 JSON。这个答案没有给你 JSON。
          • 如果你想打印一些东西的表示,为什么打印什么底层对象很重要?只要产生的输出忠实地代表 json,应该没问题。
          • @BallpointBen,您的代码打印数组或字典,因此它不会打印来自服务器端的真实 json。
          • @BallpointBen,我需要查看来自服务器端的确切数据,而不是修改。
          • @Dmitry 我注意到的一件事是解码,然后通过 JSONSerialization 类重新编码值似乎会弄乱浮点数。例如,我原来的 json 有 188.71 作为值,但通过编码运行它,然后重新解码产生 188.71000000000001。不知道为什么,但是不能准确地返回内容是非常令人沮丧的。只是给你一个提示。
          猜你喜欢
          • 2019-12-11
          • 1970-01-01
          • 1970-01-01
          • 2013-07-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-22
          • 1970-01-01
          相关资源
          最近更新 更多