我遇到与服务器通信的问题。 Web服务器期望JSON对象中的所有参数都是字符串。因此,每个容器中的每个数字和每个布尔值都需要是一个字符串。
对于我的例子,我有NSDictionary
个完整的键值(值是各种类型 - 数字,数组等)。例如:
{
"AnExampleNumber":7e062fa,
"AnExampleBoolean":0,
"AnExampleArrayOfNumber":[17,4,8]
}
必须成为:
{
"AnExampleNumber":"7e062fa",
"AnExampleBoolean":"0",
"AnExampleArrayOfNumber":["17","4","8"]
}
我尝试了标准NSJSONSerializer
,但它并没有给我任何选择来做我需要的事情。然后我尝试手动将字典中的所有内容转换为字符串,但这似乎是开销。有没有人暗示过我?也许是一个串行器,它只是将容器中的任何对象转换为字符串?或者是将函数转换为字符串的函数?
答案 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;
}