How to handle null response of web services - iphone

My app consuming PHP web services. But some field of response is null and i cant handle that null value.
This is my response
[
{
ID: 1,
ChapterID: 0,
Code: "FLGSV01",
Number: "0",
Text: "Swedish Flag",
VersionChanged: 1,
LastChange: "Jun 26 2013 12:00:00:000AM",
Type: "img",
info: null
}
]
I have parsed this response in my dictionary which like this
tmpDictn : {
ID = 1,
ChapterID = 1;
Code = SECH1W;
ID = 2;
LastChange = "Jun 26 2012 12:00:00:000AM";
Number = 001;
Text = "ett
\n";
Type = img;
VersionChanged = 1;
info = "<null>";
}
Now as you see value for info is Null and if i try to parse it in string than my string will be <null> but instead of this i just want it to display empty string.
I have tried this code but no luck
if ([tmpDictn objectForKey:#"info"]!=nil) {
info = [tmpDictn objectForKey:#"info"];
}
And this code gives me error of NSNull
if ([[tmpDictn objectForKey:#"info"] isEqualToString:#"<null>"]) {
info = [tmpDictn objectForKey:#"info"];
}
So how could i handle this null value?

Compare with [NSNull null]
From Docs
The NSNull class defines a singleton object used to represent null values in collection objects (which don’t allow nil values).
if([tmpDictn objectForKey:#"info"] == [NSNull null])
{
info = nil;
}
else
{
info = [tmpDictn objectForKey:#"info"]
}

info = [tmpDictn objectForKey:#"info"];
if(info == null)
{
//Handle null
}

if ([[tmpDictn objectForKey:#"info"] isKindOfClass:[NSNull class]])
{
info = [tmpDictn objectForKey:#"info"];
}

Try to use [NSNull null]
if ([tmpDictn objectForKey:#"info"]!=[NSNull null]) {
info = [tmpDictn objectForKey:#"info"];
} else {
//Handle null value
}

Related

simplify multiple filters in flutter

here is my code
value = data.where((i) => (i.type == 1 || i.type == 3)).toList();
if (data.length == 0) {
_final = null;
} else {
dataDefault = value .where((i) => i.isdefault == 1).toList();
}
if (dataDefault.length == 0) {
data[0].isdefault = 1;
}
finalvalue = dataDefault.where((i) => i.isdefault == 1).toList();
Here is my json
[
{
"id": 129,
"type": 3,
"is_default": 1
},
{
"id": 130,
"type": 1,
"is_default": 0
},
{
"id": 131,
"type": 5,
"is_default": 1
}
]
What i need is ,i need to check if the array is in type 1 or 3 if no array available i need to set first array and change as default and then i want to filter the whole array and check default field
It is working fine but i need to simplify the code and also needs to know the approach is correct
From your description, I get the original request is:
if(array not contains type1 or type3){
set array[0] to default
}
result <- get all 'is default' from array
Simplified version:
var result; // null as default
if (data != null) {
if(data.where((i) => (i.type == 1 || i.type == 3)).isEmpty) {
data[0].isdefault = 1;
}
result = data.where((i) => i.isdefault == 1).toList();
}
Or use null safety check ? and ??
if(data?.where((i) => (i.type == 1 || i.type == 3))?.isEmpty ?? false){
data[0].isdefault = 1;
}
final result = data?.where((i) => i.isdefault == 1)?.toList();

"Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions"

I really need help with refactoring or breaking up code to smaller pieces. My Xcode can't even build project because it's too complicated.
Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions
I can't break up into smaller pieces because I have to assign results of UITextField to that function to push it to BackEnd. Code is too messy.
/* That's where I'm assigning values to Bools and selections */
#objc func handleSaveMZHD()
var NalichieTehPasportBol: Bool = false
if NalichieTehPasportResponse.text == "Да"{
NalichieTehPasportBol = true
} else if NalichieTehPasportResponse.text == "Нет"{
NalichieTehPasportBol = false
}
var NalichieElektroLambiBol: Bool = false
if (ElektroLampiResponse.text == "Да"){
NalichieElektroLambiBol = true
} else if ElektroLampiResponse.text == "Нет"{
NalichieElektroLambiBol = false
}
var NalichieLiftaBol: Bool = false
if NalichieLiftaResponse.text == "Да"{
NalichieElektroLambiBol = true
} else if NalichieLiftaResponse.text == "Нет"{
NalichieElektroLambiBol = false
}
var AktTehObsledSelection: Int = 0
if AktTehnObsledovaniyaResponse.text == "аварийный"{
AktTehObsledSelection = 1
} else if self.AktTehnObsledovaniyaResponse.text == "Не аварийный"{
AktTehObsledSelection = 2
}
var BalansPrinadlejnostiSel: Int = 0
if BalansPrinadlejResponse.text == "Государственная Собственность" {
BalansPrinadlejnostiSel = 1
} else if BalansPrinadlejResponse.text == "Частная Собственность" {
BalansPrinadlejnostiSel = 2
}
var OblicovkaSel: String = ""
if OblicovkaResponse.text == "Монолит"{
OblicovkaSel = "monolith"
}else if OblicovkaResponse.text == "Кирпич"{
OblicovkaSel = "brick"
}else if OblicovkaResponse.text == "Блоки"{
OblicovkaSel = "blocks"
}else if OblicovkaResponse.text == "Облицовка"{
OblicovkaSel = "facing"
}
/* That's function itself to push all that information to BackEnd */
updaTeRecord(o_model: "property.building", id: 207, attrs: [
"street": ulicaResponse.text,
"parking_area": PlowadParkingaResponse.text,
"builded_at": GodPostroikiResponse.text,
"all_size": Int(ObwayaPlowadDomaResponse.text!),
"land_size": Int(ObwayaPlowadUchastkaResponse.text!),
"apartment_amount": Int(KolvoKvartirResponse.text!),
"porch_amount": Int(KolvoPodezdovResponse.text!),
"level_amount": KolvoEtajeiResponse.text,
"is_tech_passport" : NalichieTehPasportBol,
"entrance_state": SostoyaniePodezdResponse.text,
"entrance_energy_saving_lamps": NalichieElektroLambiBol,
"entrance_windows_count": KolvoOkonResponse.text,
"entrance_windows_material": MaterialOkonResponse.text,
"lift_provided": NalichieLiftaBol,
"conclusion_of_technical_inspection": AktTehObsledSelection,
"lift_amount": Int(KolvoLiftovResponse.text!),
"lift_installed_at": DataUstanovkiLiftaResponse.text,
"lift_lifetime": SrokEkspluatLiftaResponse.text,
"lift_last_checked": DataPoslObslLiftaResponse.text,
"lift_company": ObslujOrganizaciyaResponse.text,
"lift_payment_method": TipOplatiLiftaResponse.text,
"power_consumption": PotreblyaemayaMownostResponse.text,
"registration_of_condominium": RegestraciyaKondominimumaResponse.text,
"date_of_condominium": DataRegestraciyaKondominimumaResponse.text,
"inventory_number": InvertarniiNomerResponse.text,
"cadastral_number": KadastroviiNomerResponse.text,
"date_of_the_last_overhaul": PosledniiKapitalniiRemontResponse.text,
"energy_efficiency": KlassEnergoResponse.text,
"house_balance": BalansPrinadlejnostiSel,
"definition_isystem": InformacionnayaSystemaResponse.text,
"ip_address_isystem": InformacionnayaIPadressResponse.text,
"last_energy_audit_at": EnergoAudiotResponse.text,
"number_of_sections": KolvoSekciiResponse.text,
"service_life_of_the_building": SrokSlujbZdaniyaResponse.text,
"depreciation": IznosMZHDResponse.text,
"house_walls": OblicovkaSel
]) { (result) in
print(result)
}
Try splitting your call to updaTeRecord(o_model:id:attrs:completion:) like this:
let myAttributes: [String: Any] = [
"street": ulicaResponse.text,
"parking_area": PlowadParkingaResponse.text,
"builded_at": GodPostroikiResponse.text,
//...
"service_life_of_the_building": SrokSlujbZdaniyaResponse.text,
"depreciation": IznosMZHDResponse.text,
"house_walls": OblicovkaSel
]
updaTeRecord(o_model: "property.building", id: 207, attrs: myAttributes) { (result) in
print(result)
}
Or this may work more stable (compile without similar issues) in most cases:
var myAttributes: [String: Any] = [:]
myAttributes["street"] = ulicaResponse.text
myAttributes["parking_area"] = PlowadParkingaResponse.text
myAttributes["builded_at"] = GodPostroikiResponse.text
//...
myAttributes["service_life_of_the_building"] = SrokSlujbZdaniyaResponse.text
myAttributes["depreciation"] = IznosMZHDResponse.text
myAttributes["house_walls"] = OblicovkaSel
updaTeRecord(o_model: "property.building", id: 207, attrs: myAttributes) { (result) in
print(result)
}

check the returned value is not NULL

I trie to check if the returned value from objectForKey is not NULL
if([[fbResult objectForKey:#"current_location"]objectForKey:#"country"])
formViewController.country=[[fbResult objectForKey:#"current_location"]objectForKey:#"country"];
But i have an error on the first line
UPDATE
fbResult is a JSON string,if the user has puted ​​his city and his country in facebook it look like :
"birthday_date" = "07/*****9";
"contact_email" = "***mehdi#hotmail.fr";
"current_location" = {
city = Tunis;
country = Tunisia;
id = 11166369***;
name = "Tunis, Tunisia";
state = Qabis;
zip = "";
};
locale = "fr_FR";
name = "Mehdi ****el";
pic = "https://fbcdn-profile-a.akamaihd.net/hprofile-********_s.jpg";
sex = male;
uid = 530****;
}
and if the user did not put his country and city it look like :
{ "birthday_date" = "02/*3/19**";
"contact_email" = "kev**kevin#gmail.com";
"current_location" = "<null>";
locale = "fr_FR";
name = "Aude ***";
pic = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/4***2_**8_1112_s.jpg";
sex = female;
uid = 11***04*;
}
error is
-[NSObject(NSObject) doesNotRecognizeSelector:] + 96
Checking for existence of an object within a dictionary that is nested in another dictionary is not going to catch all occurrences of bad data.
To make your code more solid
id current_location = [fbResult objectForKey:#"current_location"];
if (current_location != nil && [current_location class] != [NSNull class]) {
id country = [current_location objectForKey:#"country"];
if (country != nil) {
formViewController.country= country;
} else {
// current_location has no country
}
} else {
// fbResult has no current_location
}
If the current_location is supposed to be a dictionary you can swap out id currentLocation with NSDictionary * currentLocation
from your update, your current_location can potentially be an instance of NSNull
you can check against that with
[yourObject class] != [NSNull class]

How do I parse this nested JSON output in Objective C?

I'm trying to parse a nested JSON output like this in Objective C:
{
-Status: {
code: 200
request: "geocode"
name: "1.304044,103.833867"
}
-Placemark: [
-{
-Point: {
-coordinates: [
103.834
1.30396
0
]
}
-AddressDetails: {
-Country: {
CountryName: "Singapore"
-Thoroughfare: {
ThoroughfareName: "Bus stop at Lucky Plaza (09048)"
}
CountryNameCode: "SG"
}
Accuracy: 9
}
id: "p1"
address: "Bus stop at Lucky Plaza (09048)"
}
-{
-Point: {
-coordinates: [
103.834
1.30444
0
]
}
-AddressDetails: {
-Country: {
CountryName: "Singapore"
AddressLine: "Lucky Plaza"
-Thoroughfare: {
-PostalCode: {
PostalCodeNumber: "238863"
}
ThoroughfareName: "304 Orchard Road"
}
CountryNameCode: "SG"
}
Accuracy: 9
}
id: "p2"
address: "Lucky Plaza, 304 Orchard Road, Singapore 238863"
}
-{
-Point: {
-coordinates: [
103.833
1.30376
0
]
}
-AddressDetails: {
-Country: {
CountryName: "Singapore"
AddressLine: "Wisma Atria"
-Thoroughfare: {
-PostalCode: {
PostalCodeNumber: "238877"
}
ThoroughfareName: "435 Orchard Road"
}
CountryNameCode: "SG"
}
Accuracy: 9
}
id: "p3"
address: "Wisma Atria, 435 Orchard Road, Singapore 238877"
}
-{
-Point: {
-coordinates: [
103.835
1.30389
0
]
}
-AddressDetails: {
-Country: {
CountryName: "Singapore"
-Thoroughfare: {
-PostalCode: {
PostalCodeNumber: "238860"
}
ThoroughfareName: "291 Orchard Road"
}
CountryNameCode: "SG"
}
Accuracy: 9
}
id: "p4"
address: "291 Orchard Road, Singapore 238860"
}
-{
-Point: {
-coordinates: [
103.834
1.30491
0
]
}
-AddressDetails: {
-Country: {
CountryName: "Singapore"
AddressLine: "Kimsia Park"
-Thoroughfare: {
-PostalCode: {
PostalCodeNumber: "228968"
}
ThoroughfareName: "1 Jalan Kayu Manis"
}
CountryNameCode: "SG"
}
Accuracy: 9
}
id: "p5"
address: "Kimsia Park, 1 Jalan Kayu Manis, Singapore 228968"
}
]
}
I have some code working, but I'm finding the nested nature of this to be pretty tough to figure out. What I'd like to get out is an array/dictionary which contains the following elements for each return record: coordinates, CountryName, ThoroughfareName, PostalCode and Accuracy.
Here is my test code so far:
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *jsonURL = [NSURL URLWithString:#"http://gothere.sg/maps/geo?output=json&ll=1.304044%2C103.833867&client=&sensor=false&callback="];
NSString *jsonData = [[NSString alloc] initWithContentsOfURL:jsonURL];
self.jsonArray = [jsonData JSONValue];
NSLog(#"%#", jsonArray);
[jsonURL release];
[jsonData release];
}
My code just manages to get the raw JSON output, any thoughts/code to break it down as I've mentioned above.
Thanks!
As requested, some further information.
Using SBJson framework.
NSLog output from above:
2011-08-30 16:44:32.605 Taxi[53070:207] {
Placemark = (
{
AddressDetails = {
Accuracy = 9;
Country = {
CountryName = Singapore;
CountryNameCode = SG;
Thoroughfare = {
ThoroughfareName = "Bus stop at Lucky Plaza (09048)";
};
};
};
Point = {
coordinates = (
"103.834",
"1.30396",
0
);
};
address = "Bus stop at Lucky Plaza (09048)";
id = p1;
},
{
AddressDetails = {
Accuracy = 9;
Country = {
AddressLine = "Lucky Plaza";
CountryName = Singapore;
CountryNameCode = SG;
Thoroughfare = {
PostalCode = {
PostalCodeNumber = 238863;
};
ThoroughfareName = "304 Orchard Road";
};
};
};
Point = {
coordinates = (
"103.834",
"1.30444",
0
);
};
address = "Lucky Plaza, 304 Orchard Road, Singapore 238863";
id = p2;
},
{
AddressDetails = {
Accuracy = 9;
Country = {
AddressLine = "Wisma Atria";
CountryName = Singapore;
CountryNameCode = SG;
Thoroughfare = {
PostalCode = {
PostalCodeNumber = 238877;
};
ThoroughfareName = "435 Orchard Road";
};
};
};
Point = {
coordinates = (
"103.833",
"1.30376",
0
);
};
address = "Wisma Atria, 435 Orchard Road, Singapore 238877";
id = p3;
},
{
AddressDetails = {
Accuracy = 9;
Country = {
CountryName = Singapore;
CountryNameCode = SG;
Thoroughfare = {
PostalCode = {
PostalCodeNumber = 238860;
};
ThoroughfareName = "291 Orchard Road";
};
};
};
Point = {
coordinates = (
"103.83499999999999",
"1.30389",
0
);
};
address = "291 Orchard Road, Singapore 238860";
id = p4;
},
{
AddressDetails = {
Accuracy = 9;
Country = {
AddressLine = "Kimsia Park";
CountryName = Singapore;
CountryNameCode = SG;
Thoroughfare = {
PostalCode = {
PostalCodeNumber = 228968;
};
ThoroughfareName = "1 Jalan Kayu Manis";
};
};
};
Point = {
coordinates = (
"103.834",
"1.30491",
0
);
};
address = "Kimsia Park, 1 Jalan Kayu Manis, Singapore 228968";
id = p5;
}
);
Status = {
code = 200;
name = "1.304044,103.833867";
request = geocode;
};
}
Try this :
//NSMutableArray *addressDetails = [[NSMutableArray alloc] init];
NSMutableArray *addressDetails = [[jsonArray valueForKey:#"Placemark"] valueForKey:#"AddressDetails"];
//NSMutableArray *point = [[NSMutableArray alloc] init];
NSMutableArray *point = [[jsonArray valueForKey:#"Placemark"] valueForKey:#"Point"];
NSLog(#"%#", point);
NSLog(#"%#", [point objectAtIndex:0]);
NSLog(#"%#", addressDetails);
Like wise you can get array of "id" and "address" value also.
To get value of "coordinates" of point array, do this
NSLog(#"%#", [[point objectAtIndex:0] valueForKey:#"coordinates"]);
For AddressDetails/Country/CountryName :
NSLog(#"%#", [[[addressDetails objectAtIndex:0] valueForKey:#"Country"] valueForKey:#"CountryName"]);
Your json is invalid, try to test it on http://jsonviewer.stack.hu/ once it becames valid then only you can use it. You must have used the SBJSON framework to parse it.

parse value from a dictionary/list

I have a dictionary/list balance_sign_dict from which I need to retrieve 2 values based on condition.
The source XML for this is;
<Value>
<Signature>-873</Signature>
<Amount>1501042000</Amount>
</Value>
I want to parse data from the dict shown below;
Could you please tell me how do I parse conditional data (e.g. if I want the value of "Amount" node for "Signature" node having -873) i.e. it should return me 1501042000
I want a generic way of parsing the values from the dictionary below.
Printing description of balance_sign_dict:
(
{
nodeChildArray = (
{
nodeContent = "-873";
nodeName = Signature;
},
{
nodeContent = 1501042000;
nodeName = Amount;
}
);
nodeName = Value;
},
{
nodeChildArray = (
{
nodeContent = "-1228";
nodeName = Signature;
},
{
nodeContent = 428586000;
nodeName = Amount;
}
);
nodeName = Value;
},
{
nodeChildArray = (
{
nodeContent = "-1140";
nodeName = Signature;
},
{
nodeContent = 79370000;
nodeName = Amount;
}
);
nodeName = Value;
},
Here is what I am trying now;
for (NSDictionary *valueNode in balance_sign_dict){
for (NSArray *nodeChildArray in [valueNode objectForKey:#"nodeChildArray"]){
NSString *tmpNodeName = [nodeChildArray objectAtIndex:1];
NSDictionary *tmpD = [valueNode objectAtIndex:1];
if ([tmpNodeName isEqualToString:#"Signature"]) {
tmpSignVal = [nodeChildArray objectAtIndex:0];
if ([tmpSignVal isEqualToString:#"-873"]) {
tmpSignAmt = [nodeChildArray objectAtIndex:1];
}
}
But for some reason the 2nd part of nodeChildArray gets removed...i.e. nodeContent = 1501042000;
nodeName = Amount;
I am not sure how to access that part.
Please help.
}
}
Actually here is what i get during alternate runs;
Printing description of nodeChildArray:
{type = mutable dict, count = 2,
entries =>
0 : {contents = "nodeName"} = {contents = "Signature"}
1 : {contents = "nodeContent"} = {contents = "-1507"}
}
Printing description of nodeChildArray:
{type = mutable dict, count = 2,
entries =>
0 : {contents = "nodeName"} = {contents = "Amount"}
1 : {contents = "nodeContent"} = {contents = "631000"}
}
How do I get the Amount value for matching Signature value?
NSArray and NSDictionary are the best container classes that I know of in any language that I am experienced with. NSDictionary can store any object or primitive, including an NSArray, and vice versa. When I say dictionary I am arbitrarily referring to either class.
When you output the description of any dictionary (which is as simple as NSLog(#"%#",myDict);, the entire contents of the dictionary are displayed like an XML (or maybe more accurately a JSON) document. It is easy to look at the content of the dictionary description to determine what is contained inside. () denotes an NSArray and {} denotes an NSDictionary.
// this is the beginning of an array.
(
// this is the beginning of index 0 of the array, an `NSDictionary`
{
// objectForKey:#"nodeChildArray"] isKindOfClass:[NSArray class]]
nodeChildArray = ( // inside nodeChildArray is another array
{ // index 0 of array is a dictionary with two keys
// objectForKey:#"nodeContent" == #"-873"
nodeContent = "-873";
// objectForKey:#"nodeName" == #"Signature"
nodeName = Signature;
}, // end of index 0
{ // index 1 of array
nodeContent = 1501042000;
nodeName = Amount;
} // end of index 1
); // end of nodeChildArray, an NSArray stored at objectForKey:#"nodeChildArray"
// this is the only other element in the dictionary, a string
// objectForKey:#"nodeName"] isKindOfClass:[NSString class]]
nodeName = Value;
}, // end of the dictionary containing nodeChildArray and nodeName
{ // objectAtIndex:1
nodeChildArray = (
{
nodeContent = "-1228";
nodeName = Signature;
},
{
nodeContent = 428586000;
nodeName = Amount;
}
);
nodeName = Value;
},
{ // objectAtIndex:2
nodeChildArray = (
{
nodeContent = "-1140";
nodeName = Signature;
},
{
nodeContent = 79370000;
nodeName = Amount;
}
);
nodeName = Value;
},
);
So you can see from looking at your NSDictionary debug output that it's actually an NSArray. The order of structures is NSArray->NSDictionary->NSArray->NSString <--> [[[[NSArray objectAtIndex:i] NSDictionary objectForKey:#"nodeChildArray"] NSArray objectAtIndex:j] NSDictionary objectForKey:#"nodeContent"], finally returning an NSString. Use this as the most recent code - in the last version of the code I passed balance_sign_dict as an NSDictionary. This might have even worked! But it is much better form to cast the argument properly. If you don't know whether or not your dictionary is going to start with an NSArray or an NSDictionary, you can cast it as an id and check its type with [theIdObject isKindOfClass:[{NSArray,NSDictionary} class]]. Don't use the {} and choose one of the two in your code.
-(NSDictionary*)parseBalance:(NSArray*)balance_sign_dict
{
NSMutableDictionary* theResults = [NSMutableDictionary dictionary];
for( NSDictionary* nodeDict in balance_sign_dict )
{
NSArray* nodeChildArray = [nodeDict objectForKey:#"nodeChildArray"];
[theResults addObject:[[nodeChildArray objectAtIndex:1] objectForKey:#"nodeContent"] forKey:[[nodeChildArray objectAtIndex:0] objectForKey:#"nodeContent"]];
}
return theResults;
}