将Container的所有值转换为NSString

时间:2015-04-01 13:01:17

标签: ios objective-c json

我遇到与服务器通信的问题。 Web服务器期望JSON对象中的所有参数都是字符串。因此,每个容器中的每个数字和每个布尔值都需要是一个字符串。

对于我的例子,我有NSDictionary个完整的键值(值是各种类型 - 数字,数组等)。例如:

{
"AnExampleNumber":7e062fa,
"AnExampleBoolean":0,
"AnExampleArrayOfNumber":[17,4,8]
}

必须成为:

{
"AnExampleNumber":"7e062fa",
"AnExampleBoolean":"0",
"AnExampleArrayOfNumber":["17","4","8"]
}

我尝试了标准NSJSONSerializer,但它并没有给我任何选择来做我需要的事情。然后我尝试手动将字典中的所有内容转换为字符串,但这似乎是开销。有没有人暗示过我?也许是一个串行器,它只是将容器中的任何对象转换为字符串?或者是将函数转换为字符串的函数?

2 个答案:

答案 0 :(得分:2)

这是你可以做到的一种方式。它没有经过优化,没有错误处理。它仅支持NSJSONSerializer支持的各种对象。

#import <Foundation/Foundation.h>

@interface NSObject(SPWKStringify) 
- (id)spwk_stringify;
@end

@implementation NSObject(SPWKStringify) 
- (id)spwk_stringify
{
    if ([self isKindOfClass:[NSDictionary class]]) {
        NSDictionary *dict = (NSDictionary *)self;
        NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init];

        for (NSString *key in [dict allKeys]) {
            newDict[key] = [dict[key] spwk_stringify];
        }

        return newDict;
    } else if ([self isKindOfClass:[NSArray class]]) {
        NSMutableArray *newArray = [[NSMutableArray alloc] init];

        for (id value in ((NSArray *)self)) {
            [newArray addObject:[value spwk_stringify]];
        }

        return newArray;
    } else if (self == [NSNull null]) {
        return @"null"; // representing null as a string doesn't make much sense
    } else if ([self isKindOfClass:[NSString class]]) {
        return self;
    } else if ([self isKindOfClass:[NSNumber class]]) {
        return [((NSNumber *)self) stringValue];
    }

    return nil;
}
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSDictionary *dict = @{
            @"AnExampleNumber": @1234567,
            @"AnExampleBoolean": @NO,
            @"AnExampleNull": [NSNull null],
            @"AnExampleArrayOfNumber": @[@17, @4, @8],
            @"AnExampleDictionary": @{@"innerKey": @[@55, @{@"anotherDict": @[@"foo", @[@1, @2, @"three"]]}]}
        };

        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[dict spwk_stringify] options:NSJSONWritingPrettyPrinted error:NULL]; 
        NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

        NSLog(@"result: %@", jsonString);
    }
}

输出将是:

result: {
  "AnExampleNumber" : "1234567",
  "AnExampleNull" : "null",
  "AnExampleDictionary" : {
    "innerKey" : [
      "55",
      {
        "anotherDict" : [
          "foo",
          [
            "1",
            "2",
            "three"
          ]
        ]
      }
    ]
  },
  "AnExampleBoolean" : "0",
  "AnExampleArrayOfNumber" : [
    "17",
    "4",
    "8"
  ]
}

注意:请注意,将[NSNull null]转换为字符串并没有任何意义,实际上可能会产生误导和危险。

享受。

答案 1 :(得分:1)

(我假设您的意思是NSJSONSerializer,而不是NSSerializer。)

我怀疑你会找到预先解决的解决方案。这不是一般问题。如您所知,这是不正确的JSON,因此JSON序列化程序不应该这样做。

最佳解决方案IMO只需编写代码即可将您的NSDictionary转换为您想要的另一种NSDictionary。如果您真的想让它成为通用解决方案,我怀疑使用NSDictionary的自定义isKindOfClass:助行器是您最好的选择。这样的事情应该有效:

NSDictionary *myStringDictForDict(NSDictionary *dict); // forward decl if needed

NSArray *myStringArrayForArray(NSArray *array) {
    NSMutableArray *result = [NSMutableArray new];
    [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if ([obj isKindOfClass:[NSArray class]]) {
            [result addObject:myStringArrayForArray(obj)];
        } else if ([obj isKindOfClass:[NSDictionary class]]) {
            [result addObject:myStringDictForDict(obj)];
        } else {
            [result addObject:[obj description]];
        }
    }];

    return result;
}

NSDictionary *myStringDictForDict(NSDictionary *dict) {
    NSMutableDictionary *result = [NSMutableDictionary new];
    [dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
       if ([obj isKindOfClass:[NSArray class]]) {
            result[key] = myStringArrayForArray(obj);
        } else if ([obj isKindOfClass:[NSDictionary class]]) {
            result[key] = myStringDictForDict(obj);
        } else {
            result[key] = [obj description];
        }
    }];

    return result;
}