How do I get NSJSONSerialization to output a boolean as true or false?
Asked Answered
D

6

28

I'm using NSJSONSerialization dataWithJSONObject to serialize my classes to JSON. When it serializes a BOOL, it gives it the value 1 or 0 in the JSON string. I need this to be true or false instead. Is this possible to do generically?

Doradorado answered 28/11, 2012 at 22:21 Comment(0)
D
3

No, the Foundation Object for a Bool is NSNumber numberWithBool, which becomes either 0 or 1. We have no Bool Object. Same go for reading JSON. True/false will become a NSNumber again.

You could create an Bool Class and build your own parser. Arrays are Arrays and JSON Objects are NSDictionary. You can query the keys, test what Class lies behind and build the JSON String from this.

Drastic answered 28/11, 2012 at 22:51 Comment(4)
thanks, I created my own JSONBool class and was able to get it working like thatDoradorado
@TritonMan mind posting more of the code in the JSONBool class? Trying to accomplish the same thing.Viminal
Yes, the way how NSJSONSerialization works changed over the years. Please note the date when this question was asked and answered.Drastic
@Julian's answer below with [NSNumber numberWithBool:NO] is much simpler nowadaysUltima
L
30

When I create [NSNumber numberWithBool:NO], the NSJSONSerialization returns the word "false" in the JSON string.

EDIT With the new shortcuts you can also use these handy guys:

@(YES) /   @(NO)
@(1)   /   @(0)
@YES   /   @NO
@1     /   @0

This way you can avoid something like looping through your values. I want the exact opposite behavior but have NSNumber objects. So I have to loop...

EDIT II

mbi pointed out in the comments that there is a difference between iOS versions. So here is an iOS9 test:

NSDictionary *data = @{
    @"a": @(YES),
    @"b": @YES,
    @"c": @(1),
    @"d": @1
};
NSLog(@"%@", [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:data options:0 error:nil] encoding:NSUTF8StringEncoding]);

2016-07-05 02:23:43.964 Test App[24581:6231996] {"a":true,"b":true,"c":1,"d":1}
Lyris answered 21/6, 2013 at 11:59 Comment(3)
There is a little caveat between iOS versions here! This code [NSJSONSerialization dataWithJSONObject:@{ @"Test1" : @YES, @"Test2" : @(YES), @"Test3" : @true, @"Test4" : @(true) } options:nil error:nil] produces this json on iOS 9 {"Test4":true,"Test3":true,"Test2":true,"Test1":true} but produces this json on iOS 8 and below {"Test4":1,"Test3":1,"Test2":true,"Test1":true}Revocation
Interesting... Thanks for this observation!Lyris
No, I didnt see that. I will delete my comment. Thanks for pointing out!Drastic
C
15

Just ran across this myself, not sure if this is the best answer but...

Make sure to use @YES or @NO, then your outputted json will have true / false in it:

[NSJSONSerialization dataWithJSONObject:@{@"test": @YES} options:0 error: nil];

So you will have to turn your other "booleans" / boolean like values -> @YES / @NO when putting into the dictionary for dataWithJSONObject.

[NSJSONSerialization dataWithJSONObject:@{@"test": (boolLikeValue ? @YES : @NO)} options:0 error: nil];
Colic answered 4/3, 2014 at 21:41 Comment(1)
I find this helpful since not always one can use literals directly. e.g. In a function receiving a BOOL parameter, you'll need to convert the primitive BOOL to one of the acknowledgeable @BOOL literals` @YES` and @NOSquamation
H
5

Yes, it is possible to output a boolean (true/false) with NSJSONSerialization by using kCFBooleanTrue and kCFBooleanFalse :

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:kCFBooleanTrue, @"key_1",
                           kCFBooleanFalse, @"key_2",
                           nil]  

then

NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:kNilOptions error:&error];
Hi answered 11/2, 2015 at 9:5 Comment(0)
D
3

No, the Foundation Object for a Bool is NSNumber numberWithBool, which becomes either 0 or 1. We have no Bool Object. Same go for reading JSON. True/false will become a NSNumber again.

You could create an Bool Class and build your own parser. Arrays are Arrays and JSON Objects are NSDictionary. You can query the keys, test what Class lies behind and build the JSON String from this.

Drastic answered 28/11, 2012 at 22:51 Comment(4)
thanks, I created my own JSONBool class and was able to get it working like thatDoradorado
@TritonMan mind posting more of the code in the JSONBool class? Trying to accomplish the same thing.Viminal
Yes, the way how NSJSONSerialization works changed over the years. Please note the date when this question was asked and answered.Drastic
@Julian's answer below with [NSNumber numberWithBool:NO] is much simpler nowadaysUltima
W
1

I ran into similar issue when using CoreData's boolean, which is stored as NSNumber too. The easiest solution for me was using @():

[NSJSONSerialization dataWithJSONObject:@{@"bool": @([object.value boolValue])} options:0 error: nil];

I guess @() does recognize the BOOL value and initialize the NSNumber with numberWithBool: which leads to true/false in JSON

Ween answered 13/8, 2014 at 23:48 Comment(0)
W
1

I just hit the issue on iOS9. My case is that I have a CoreData property workout.private which is bool mapped to NSNumber* due to CoreData handling.

When creating JSON [NSNumber numberWithBool:workout.private.boolValue] sets expected true/false in JSON, but just workout.private or @(workout.private.boolValue) sets "1" or "0".

Weissman answered 8/10, 2016 at 17:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.