将包含 NSArray 的 NSDictionary 转换为 JSON

Posted

技术标签:

【中文标题】将包含 NSArray 的 NSDictionary 转换为 JSON【英文标题】:Convert NSDictionary containing NSArray to JSON 【发布时间】:2014-05-11 21:54:08 【问题描述】:

我有一个 NSDictionary 包含几个不同的对象,其中有一个 NSArray

数组中的元素是自定义对象的NSDictionary-表示。为简单起见,我已重命名属性并删除了其他一些属性。

首先我尝试像这样简单地序列化NSArray,只是为了看看它会是什么样子:

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:myArray options:NSJSONWritingPrettyPrinted error:&writeError];
NSLog(@"%@", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]);

结果看起来像这样,这是我所期望的:

[
  
    "someProperty" : "Value 1"
  ,
  
    "someProperty" : "Value 2"
  
]

但是,当我将(未编码的)数组添加到 NSDictionary 并对其进行序列化时,数组看起来不同:

NSMutableArray *myArray = [NSMutableArray array];
[myArray addObject:[object1 dictionaryRepresentation]]; // dictionaryRepresentation returns a NSDictionary
[myArray addObject:[object2 dictionaryRepresentation]];

NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setObject:myArray forKey:@"myArray"];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:&writeError];
NSLog(@"%@", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]);

现在结果如下所示:


  myArray =     (
                  
            "someProperty" : "Value 1"
        ,
                  
            "someProperty" : "Value 2"
        
  );

我没有得到"myArray" : [...],而是得到myArray = (...);,这不是正确的JSON表示。

在将NSArray 添加到字典时,使用 JSON 表示的正确方法是什么?

【问题讨论】:

对你的“Now”结果的最佳(虽然不完美)解释是,你从第一个字典中获取了编码的 JSON,转换为 NSString,然后将其添加到第二个字典中。这不是应该做的。您应该将第一个字典本身而不是它的 JSON 表示添加到第二个字典。一切都应该同时进行 JSON 编码,只需一个操作。 (如果您向我们展示进行编码的代码,包括产生上述输出的 NSLog 语句,将会有所帮助。) 我相信我现在理解了这种困惑。看起来我正在获取NSArray 的编码表示(来自第一个代码sn-p)并将其添加到我的NSDictionary(在第二个代码sn-p 中)。事实上,这两个代码 sn-ps 根本没有一起使用。正如我在问题中解释的那样,我只使用第一个 sn-p 中的代码来测试 NSArray 的序列化会是什么样子。我现在提供了额外的代码行来解释我实际上对数组做了什么。对于不明确之处,我深表歉意。 重点是您上面的最终“JSON”列表不是有效的 JSON,也不是在 NSLogging 上看到的表示有效 JSON 的 NSDictionary。注意“myArray”没有被引用,后面跟着=,与字典的NSLog一致,而“someProperty”引用,后面跟着:,与JSON一致。你没有向我们展示真实数据。 (一个 JSON "object" 包含引用的键值,并使用 : 将键与值分隔。NSDictionary 的 NSLog 仅在键值包含非字母字符时引用它们,并将键与值分隔带有=。此外,JSON“对象”被[]“括起来”,而字典的NSLog用()括起来。) 【参考方案1】:

在第一种情况下,您正在打印 JSON 编码操作的结果。

在第二种情况下,您直接通过NSLog 打印出字典,而不是它的 JSON 表示。

更新:

要查看此内容,请使用此日志记录功能而不是 NSLog

void logThisObject(id obj)

    if(obj == nil) 
        NSLog(@"logObject: nil");
     else 
        NSString *className = NSStringFromClass([obj class]);
        NSLog(@"logObject: an %@: %@", className, obj);
    

更新 2:

void test_it()

    NSArray *myArray = @[@"bla", @"foo"];
    NSError *writeError = nil;

    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
    [dictionary setObject:myArray forKey:@"myArray"];
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:&writeError];
    if(writeError) 
        NSLog(@"an error happened: %@", writeError);
    
    logThisObject([[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]);

这会输出正确的 JSON 字符串:

logObject: an __NSCFString: 
  "myArray" : [
    "bla",
    "foo"
  ]

【讨论】:

第二种情况不是完全你从字典/数组的 NSLog 中看到的,但我认为 OP 只是近似结果的外观案子。实际输出将具有 = 而不是 :,并且在不包含任何空格或非字母字符的字符串周围没有引号。 @HotLicks 第二种情况是我从我包含的代码中得到的。 myArray 中的元素是 NSDictionary - 自定义对象的表示形式。不过,为了简单起见,我确实重命名了这些属性并删除了其他一些属性。 @Michael 我在第二种情况下打印的是字典的 endoded JSON(当然转换为NSString)。但是,当我将NSArray 添加到NSDictionary 时,我假设它使用的数组表示与NSLog 使用的数组相同,因此结果看起来相同。我需要知道的是在将其添加到字典时使用NSArray 的 JSON 表示的正确方法。 @NobleK:我更新了我的答案。似乎您正在对字典进行 JSON 编码,丢弃结果,然后打印出未编码的字典。也许你可以用一段独立的代码重现这个问题,我可以复制粘贴到 Xcode 中? 今天再次查看我的代码,我发现您实际上是正确的,因为在我大量的控制台日志记录中,我实际上是在查看错误的输出。我在问题中提供的内容(以及让我相信存在问题的原因)实际上来自 NSDictionary 的直接输出,而不是 JSON 表示。感谢您的帮助,并为我的固执道歉。

以上是关于将包含 NSArray 的 NSDictionary 转换为 JSON的主要内容,如果未能解决你的问题,请参考以下文章

检索数据并将 JSON 记录保存在数组中

如何从包含任意对象的 NSSet 创建排序的 NSArray?

如何将 NSDictionarys 的 NSArray 变成 NSDictionarys 的嵌套 NSArray

如何序列化包含 NSNull 的 NSDictionary/NSArray/Property List (plist)

从 NSArray 过滤 NSDictionary

根据 NSDictionary 键值将 NSArray 拆分为子数组