NSNull returns <null> instead of returning null - ios

I'm using the following code to check if a NSNumber has nil value. So I'm converting the NSNumber to string and Im checking if its length is 0. If it is of zero, Im returning NSNull else Im returning the number itself.
- (id)NSNullToNilForKey:(NSNumber *)number
{
if ([[number stringValue] length] == 0){
return [NSNull null];
}
return number;
}
Im invoking it as follows,
NSString *bodyString = [NSString stringWithFormat:#"[ \"%#\",{\"session_token\": \"%#\",\"request\": [\"GetAssigneeWiseCompliancesChart\",{\"country_id\": %#,\"business_group_id\": %#,\"legal_entity_id\": %#,\"division_id\": %#,\"unit_id\": %#,\"user_id\": %#}]}]",clientSessionId,clientSessionId,[self NSNullToNilForKey:countryId],[self NSNullToNilForKey:businessGroupId],[self NSNullToNilForKey:legalEntityId],[self NSNullToNilForKey:divId],[self NSNullToNilForKey:unitId], [self NSNullToNilForKey:userId]];
But the problem is that, though the if loop is getting invoked. The value returned from the if loop of NSNullToNilForKey is <null> instead of null. How can I sort this out?

You're creating a string from a format, all of the parameters are added by taking their description, what you're seeing is the description of the NSNull instance.
Your method should specifically return a string and you should choose explicitly what string you want to return.
- (id)NSNullToNilForKey:(NSNumber *)number
{
if ([[number stringValue] length] == 0){
return #"NSNull";
}
return number;
}

try this
change the type anyobject id to NSNumber *
- (NSNumber *)NSNullToNilForKey:(NSNumber *)number
{
if ([[number stringValue] length] == 0){
return [NSNull null];
}
return number;
}

Related

How to check if json object contains <null>?

I am getting a Json from server by making a network request in my app.I am getting <null> value for some keys in Json object.My app gets crashed if this type of response is received.Please tell me how can i validate>?
I have tried this but it does not work all time.
if(!(user_post.username==(id)[NSNull null]) )
{
user_post.username=[dict_user_info objectForKey:#"name"];
if(user_post.username!=nil)
{
ser_post.username=[dict_user_info objectForKey:#"name"];
}
else
{
user_post.username=#"Username";
}
}
Consider testing the value for null so your program won't crash. Like this:
if([dict_user_info objectForKey:#"name"] != [NSNull null])
{
ser_post.username=[dict_user_info objectForKey:#"name"];
}
Create a Category of NSDictionary and add following method in it, which replaces null value with empty string for each key in dictionary.
- (NSDictionary *)dictionaryByReplacingNullsWithStrings
{
const NSMutableDictionary *replaced = [self mutableCopy];
const id nul = [NSNull null];
const NSString *blank = #"";
for(NSString *key in self) {
const id object = [self objectForKey:key];
if(object == nul || object == NULL) {
//pointer comparison is way faster than -isKindOfClass:
//since [NSNull null] is a singleton, they'll all point to the same
//location in memory.
[replaced setObject:blank
forKey:key];
}
}
return [replaced copy];
}
Usage :
[yourJSONDictionary dictionaryByReplacingNullsWithStrings];
Read more about Category in iOS Tutorial 1 and Tutorial 2
yourJsonObject = [myDic valueforkey#"key"];
if(yourJsonObject != [NSNull null])
{
//not null
}
** you can also check whether object exist or not
if(yourJsonObject)
{
//exist
}
I think you've confused your logic. I am trying to stay true to your code, but let me know if the following is not what you intended:
if (dict_user_info[#"name"] != nil && [dict_user_info[#"name"] isKindOfClass:[NSNull class]] == NO) {
user_post.username = dict_user_info[#"name"];
if (user_post.username != nil) {
ser_post.username = user_post.username;
} else {
user_post.username = #"Username";
}
}
These are a couple of methods I wrote for my projects, try them :
/*!
* #brief Makes sure the object is not NSNull or NSCFNumber, if YES, converts them to NSString
* #discussion Sometimes JSON responses can contain NSNull objects, which does not play well with Obj-C. So when you access a value from a JSON and expect it to be an NSString, pass it through this method just to make sure thats the case.
* #param str The object that is supposed to be a string
* #return The object cleaned of unacceptable values
*/
+ (NSString *)cleanedJsonString:(id)str
{
NSString *formattedstr;
formattedstr = (str == [NSNull null]) ? #"" : str;
if ([str isKindOfClass:[NSNumber class]]) {
NSNumber *num = (NSNumber*) str;
formattedstr = [NSString stringWithFormat:#"%#",num];
}
return formattedstr;
}
/*!
* #brief Makes Sure the object is not NSNull
* #param obj Sometimes JSON responses can contain NSNull objects, which does not play well with Obj-C. So when you access a value from a JSON ( NSArray, NSDictionary or NSString), pass it through this method just to make sure thats the case.
* #return The object cleaned of unacceptable values
*/
+ (id)cleanedObject:(id)obj
{
return (obj == [NSNull null]) ? nil : obj;
}
/*!
* #brief A JSON cleaning function for NSArray Objects.
* #discussion Sometimes JSON responses can contain NSNull objects, which does not play well with Obj-C. So when you access a value from a JSON and expect it to be an NSArray, pass it through this method just to make sure thats the case. This method first checks if the object itself is NSNull. If not, then it traverses the array objects and cleans them too.
* #param arr The Objects thats supposed to be an NSArray
* #return The NSNull Cleaned object
*/
+ (NSArray *)cleanedJsonArray:(id)arr
{
if (arr == [NSNull null]) {
return [[NSArray alloc] init];
}
else
{
NSMutableArray *arrM = [(NSArray*)arr mutableCopy];
int i=0;
for (id __strong orb in arrM)
{
if (orb == [NSNull null])
{
[arrM removeObjectAtIndex:i];;
}
i++;
}
return arrM;
}
}
Just pass a JSON string, array or object to the appropriate method and the method will clean it for you.
Do yourself a favour and write a method that handles this and put it into an extension. Like
- (NSString*)jsonStringForKey:(NSString*)key
{
id result = self [key];
if (result == nil || result == [NSNull null]) return nil;
if ([result isKindOfClass:[NSString class]]) return result;
NSLog (#"Key %#: Expected string, got %#", key, result);
return nil;
}
You might even add some code that accepts NSNumber* results and turns them into strings, if that is what your server returns (some poster here had the problem that his server returned dress sizes as numbers like 40 or strings like "40-42" which makes something like this useful).
And then your code becomes one readable line
user_post.username = [dict_user_info jsonStringForKey:#"name"] ?: #"username";
I actually use several slightly different methods depending on whether I expect null, expect no value, expect an empty string or not, which gives me warnings when my assumptions are wrong (but always returns something that doesn't break).
try this:
if(!(user_post.username == (NSString *)[NSNull null]) )

Check if contain Null

When I print the following I get (null)
NSLog(#"%#", [[responseObject objectAtIndex:i] objectForKey:#"child"]);
Now I want to do a validation to check if it returns (null). How am I supposed to do this?
I tried the following but it doesn't work:
1.
if (![[[responseObject objectAtIndex:i] objectForKey:#"child"] isEqualToString:#"(null)"]) {
}
2.
if (![[[responseObject objectAtIndex:i] objectForKey:#"child"] isEqual:#"(null)"]) {
}
"null" isn't just a NSString. You should do some research into the concept of a null object.
What you're looking for can be written like this:
if (![[responseObject objectAtIndex:i] objectForKey:#"child"]) {
//key "child" not in dictionary
}
(null) is the representation of nil displayed by NSLog.
You can write the following:
if ([[responseObject objectAtIndex:i] objectForKey:#"child"] == nil) {
}
Or a shorter alternative:
if (![[responseObject objectAtIndex:i] objectForKey:#"child"]) {
}
Another way to check is to use string length. I know other answers are just as good, I am just giving OP and anyone else in future some more options.
NSString *childStr = [[responseObject objectAtIndex:i]objectForKey:#"child"];
if ([childStr length] < 1)
{
//no value specified - childStr is NULL
}
else
{
//there is something in the childStr - throw a party!
}
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"hello"]) {
NSLog(#"only if not null show %#",[defaults objectForKey:#"hello"]);
}
This is a way to check it from User Defaults. It will only print if the saved object does not equal null.

ios id doesn't convert to nsinteger

I have the following response that returns from a block:
response: {
error = "";
success = 1;
}
I attempt to evaluate "success" but it never evaluates as equal to 1 only as "else":
NSLog(#"response: %#", responseObject);
NSInteger success = (NSInteger)responseObject[#"success"];
NSString *errorMessage = (NSString *)responseObject[#"error"];
if (success == 0) {
NSLog(#"success is false");
NSLog(#"JSON: %#", errorMessage);
saveCallback(NO, [self createErrorFromDescription:errorMessage]);
}else if (success == 1){
NSLog(#"success is true");
saveCallback(YES, nil);
}else{
NSLog(#"success is else");
NSLog(#"JSON: %#", errorMessage);
saveCallback(NO, [self createErrorFromDescription:errorMessage]);
}
What am I doing wrong?
NSInteger is a primitive and id is an object (actually a pointer to an object), in this case likely an NSNumber.
Directly casting the pointer to an object, to NSInteger will not transform it into a integer value type, it will just reinterpret the pointers memory as an integer.
To transform the number object to a integer value you would call integerValue on it.
(It could also be that the number is missing from the response or it could be returned as the NSNull object, hence the error checking below)
NSNumber *successNumber = responseObject[#"success"];
NSInteger success;
if (!successNumber || successNumber == [NSNull null]) {
// the response doesn't contain anything for the "success" key :(
}
// if successNumber is nil, this will be 0.
// if successNumber is the NSNull object, this will crash (unrecognized selector)
// Just be aware of both of those.
success = [successNumber integerValue];
NSInteger success = [responseObject[#"success"] integerValue];
Given that it appears you're using raw json, you need to be very careful that you don't use a NULL value; this will result in an exception.
Since there are many types of Null in Objective C, it's best to use class introspection to make sure your objects are valid.
NSDictionary *responseArray = responseObject;
NSInteger success=0;
if([responseObject isKindOfClass:[NSDictionary class]])
{
// responseObject is safe to subscript
NSNumber *successNumber = responseObject[#"success"];
// Use introspection; messaging nil doesn't cause an exception and returns nil
if ([successNumber isKindOfClass:[NSNumber class]])
{
// NSInteger is a primitive
success = [successNumber integerValue];
}
}
// If success is anything but zero, assume it's true
if (success)
{
NSLog(#"success is true");
}
else
{
NSLog(#"success is false");
}
Presumably, your success key is either 1 or 0, so you could simplify this code a bit. In general, though, this is how you'll want to deal with objects that may be NULL rather than simply nil.

iOS Incompatible pointer types returning NSDictionary from NSMutableDictionary

I'm having an issue where I use NSMutableDictionaries returns values from NSDictionary.
Here is the warning message:
incompatible pointer types returning 'NSDictionary *' from a function
with result type 'NSMutableDictionary *'
Here is the code:
- (NSMutableDictionary *)dictionaryWithContentsAtPath:(NSString *)path
{
if ([path rangeOfString:#"/SessionStore"].location == 0)
{
return [_inMemoryCache objectForKey:[path stringByReplacingCharactersInRange:NSMakeRange(0, 13) withString:#""]];
}
if ([path rangeOfString:#"/PermanentStore"].location == 0)
{
return [NSDictionary dictionaryWithContentsOfFile:[self.persistentStoragePath stringByAppendingPathComponent:[path substringFromIndex:15]]];
}
return nil;
}
Please help me how to resolve this warning.
You need to ensure you're returning the right type. Your method states it's returning an NSMutableDictionary, but then returns only an NSDictionary.
Try this instead:
- (NSMutableDictionary*)dictionaryWithContentsAtPath:(NSString*)path {
if ([path rangeOfString:#"/SessionStore"].location == 0) {
return [[_inMemoryCache objectForKey:[path stringByReplacingCharactersInRange:NSMakeRange(0, 13) withString:#""]] mutableCopy];
}
if ([path rangeOfString:#"/PermanentStore"].location == 0) {
return [NSMutableDictionary dictionaryWithContentsOfFile:[self.persistentStoragePath stringByAppendingPathComponent:[path substringFromIndex:15]]];
}
return nil;
}
Note: added a call to mutableCopy to turn your literal NSDictionary into a mutable version, and in the second case, used called the dictionaryWithContentsOfFile method on the NSMutableDictionary subclass instead of the NSDictionary parent class.

NSNumber with IF statement issue

I am loading data from a server but I have an issue that the value that I am returning is zero(0) while I can't go inside if. Please where would be the problem?
-(void)method1
{
NSNumber *value = [data objectForKey:#"samount"];
NSLog(#"number is -%#-", value); //number is -0-
if (value == 0)
{
NSLog(#" OK :) ");
}
else
{
NSLog(#" Bad :( ");
}
}
Use isEqual:
if ([value isEqual:#(0)])
That will also evaluate correctly in case value is nil (where == comparison with floatValue or similar methods would fail)
value is an object, and more precisely a NSString object (as per your comments in Alladinian's answer), but you are checking its address. You can convert your string to NSNumber with NSNumberFormatter and then check its value or rely on NSString's built-in methods: integerValue, floatValue, etc.
Assuming value is a NSNumber/NSString:
if ([value integerValue] == 0)
See Getting Numeric Values in NSString documentation and Accessing Numeric Values in the NSNumber documentation and pick the method that best suits your data type.

Resources