I am sending a request with AFNetworking for Objective-C. When I NSLog the parameters this is the object I am sending:
games = (
{
id = 50;
p = 8;
ts = 0;
tt = ();
tw = 0;
ys = 35150;
yt = {
156424496 = "37.416669";
156609008 = "56.661210";
....
252846816 = "7.075133";
252856944 = "61.329850";
};
yw = 0;
}, ...
This is what the server receives.
games = (
{id = 50;},
{p = 8;},
{ts = 0;},
{tw = 0;},
{ys = 35150;},
{
yt = {156424496 = "37.416669";};
},
{
yt = {156609008 = "56.661210";};
},
...
{
yt = {252846816 = "7.075133";};
},
{
yt = {252856944 = "61.329850";};
},
{yw = 0;},
...
It is as if it is taking each property of my object and creating a new object with it. The worse part is that it's taking the multiple objects that are in the array and putting all properties of all objects and turning them into separate object on the same depth of the array.
Here is the code I am using to send this off:
NSArray *games = [ResourceManager getAllGames];
NSMutableArray *gamesArray = [[NSMutableArray alloc] initWithCapacity:[games count]];
for(Game *g in games)
{
[gamesArray addObject:[g toDictionary]];
}
User *user = [ResourceManager getUser];
NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:gamesArray, #"games", user.id, #"user_id", nil];
NSLog(#"PARAMS: %#", params); <- this is the first block of code above
[self postPath:API_SYNC_GAMES_URL parameters:params success:^(AFHTTPRequestOperation *operation, id JSON)
{
}
I have not been able to figure out why this would be happening, and I am all out of guesses. If someone could point me in the right direction it would be very appreciated.
UPDATE
If I post a single object rather than an array of the objects it arrives at the server successfully.
I was able to solve this issue by using an NSDictionary instead of an array. Each object I have has a unique key so I used that key for the NSDictionary like so:
NSMutableDictionary *gamesArray = [[NSMutableDictionary alloc]
initWithCapacity:[games count]];
for(Game *g in games)
{
[gamesArray setObject:[g toDictionary]
forKey:[NSString stringWithFormat:#"%#", g.id]];
}
That seems to have solved the issue.
Take a look at my answer here:
How can I POST an NSArray of NSDictionaries inside an NSDictionary without problems?
It solves all your problems.
Related
I am getting a JSON response from a web service as follows into a NSDictionary
NSDictionary *fetchAllCollectionsJSONResponse = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
If I dump the output of the NSDictionary it looks correct like this
2017-10-06 10:11:46.097698+0800 NWMobileTill[396:33294] +[ShopifyWebServices fetchAllCollections]_block_invoke, {
data = {
shop = {
collections = {
edges = (
{
cursor = "eyJsYXN0X2lkIjo0NTI4NTY3MTcsImxhc3RfdmFsdWUiOiI0NTI4NTY3MTcifQ==";
node = {
description = "";
id = "Z2lkOi8vc2hvcGlmeS9Db2xsZWN0aW9uLzQ1Mjg1NjcxNw==";
};
},
{
cursor = "eyJsYXN0X2lkIjo0NTI4NTkwODUsImxhc3RfdmFsdWUiOiI0NTI4NTkwODUifQ==";
node = {
description = "Test Collection 1";
id = "Z2lkOi8vc2hvcGlmeS9Db2xsZWN0aW9uLzQ1Mjg1OTA4NQ==";
};
},
{
cursor = "eyJsYXN0X2lkIjo0NTU0OTMwMDUsImxhc3RfdmFsdWUiOiI0NTU0OTMwMDUifQ==";
node = {
description = Sovrum;
id = "Z2lkOi8vc2hvcGlmeS9Db2xsZWN0aW9uLzQ1NTQ5MzAwNQ==";
};
},
{
cursor = "eyJsYXN0X2lkIjo0NTU0OTMzODksImxhc3RfdmFsdWUiOiI0NTU0OTMzODkifQ==";
node = {
description = Badrum;
id = "Z2lkOi8vc2hvcGlmeS9Db2xsZWN0aW9uLzQ1NTQ5MzM4OQ==";
};
}
);
pageInfo = {
hasNextPage = 0;
};
};
};
};
}
I need to access the "description" attribute deep inside this structure and I cannot figure out how to do it.
I tried the following but it crashes
for (NSDictionary *dictionary in fetchAllCollectionsJSONResponse) {
NSLog(#"jongel %#", [dictionary objectForKey:#"data"]);
}
#Bilal's answer is right. This might be a bit easier to read:
NSArray *edges = fetchAllCollectionsJSONResponse[#"data"][#"shop"][#"collections"][#"edges"];
for (NSDictionary *edge in edges) {
NSString *description = edge[#"node"][#"description"];
NSLog(#"description = %#", description);
}
fetchAllCollectionsJSONResponse is a Dictionary not an Array. Try this.
NSDictionary *fetchAllCollectionsJSONResponse = nil;
NSDictionary *data = fetchAllCollectionsJSONResponse[#"data"];
NSDictionary *shop = fetchAllCollectionsJSONResponse[#"shop"];
NSDictionary *collections = fetchAllCollectionsJSONResponse[#"collections"];
NSArray *edges = fetchAllCollectionsJSONResponse[#"edges"];
// Or a shorter version
// NSArray *edges = fetchAllCollectionsJSONResponse[#"data"][#"shop"][#"collections"][#"edges"];
for (NSDictionary *edge in edges) {
NSString *cursor = edge[#"cursor"];
NSDictionary *node = edge[#"node"];
}
I Have a nested Json :
[
{
"result":"1",
"roleId":4
},
{
"projectInfo":[
{
"result":true
},
{
"Project":[
{
"ProjectId":5378,
"ProjectName":"ASAG",
"CountryId":146,
"ProjectGroupId":743,
"Description":"Axel Spinger AG"
},
{
"ProjectId":5402,
"ProjectName":"BIZ",
"CountryId":146,
"ProjectGroupId":759,
"Description":"Bizerba Win 7 BAU"
},
{
"ProjectId":5404,
"ProjectName":"BOM",
"CountryId":146,
"ProjectGroupId":743,
"Description":"Bombardier Transportation ThinApp Migration"
},
{
"ProjectId":5394,
"ProjectName":"REDBULL",
"CountryId":149,
"ProjectGroupId":762,
"Description":"Red Bull Mac Packaging"
},
{
"ProjectId":5397,
"ProjectName":"VHV",
"CountryId":146,
"ProjectGroupId":743,
"Description":"VHV Win7 Migration"
}
]
}
]
}
]
What I need is to separate it into small pieces to get value of some specific key like this answer: How to parse JSON into Objective C - SBJSON
My code is :
SBJsonParser* jParser = [[SBJsonParser alloc] init];
NSDictionary* root = [jParser objectWithString:string];
NSDictionary* projectInfo = [root objectForKey:#"projectInfo"];
NSArray* projectList = [projectInfo objectForKey:#"Project"];
for (NSDictionary* project in projectList)
{
NSString *content = [project objectForKey:#"ProjectId"];
NSLog(#"%#", content);
}
But I got the error when trying to get projectInfo from root node. Is there anything wrong with my code ? Please provide me an example to split up my JSON. Any help would be great.
You JSON contains like nested array. Just spit each content into a dictionary to get the result.
Working Code:
SBJsonParser* jParser = [[SBJsonParser alloc] init];
NSArray* root = [jParser objectWithString:string];
NSDictionary* projectDictionary = [root objectAtIndex:1];
NSArray* projectInfo = [projectDictionary objectForKey:#"projectInfo"];
NSDictionary* projectData = [projectInfo objectAtIndex:1];
NSDictionary *projectList = [projectData objectForKey:#"Project"];
NSLog(#"\n\n Result = %#",projectList
);
for (NSDictionary* project in projectList)
{
NSString *content = [project objectForKey:#"ProjectId"];
NSLog(#"\n Project Id =%#", content);
}
According to your JSON structure, your top level structure is an array, not a dictionary.
Try this:
SBJsonParser* jParser = [[SBJsonParser alloc] init];
NSArray* root = [jParser objectWithString:string];
NSDictionary* projectDictionary = [root objectAtIndex:1];
NSArray* projectInfo = [projectDictionary objectForKey:#"projectInfo"];
I have a pList looking like this when i log it:
{
Hans = {
Highscore = 0;
Name = Hans;
};
},
{
joe = {
Highscore = 0;
Name = joe;
};
},
{
Iben = {
Highscore = 0;
Name = Iben;
};
},
{
Erik = {
Highscore = 0;
Name = Erik;
};
}
I would really like to make these values in my pList into objects of Players when ViewDidLoad is called. Im not sure how to do so thought. Can somebody maybe help?
Load the plist into an array (appears you already have this but still I added this step)
NSString *path = [[NSBundle mainBundle] pathForResource:#"PlayerData" //Filename
ofType:#"plist"];
NSArray *loadedArray = [[NSArray alloc] initWithContentsOfFile:path];
Create an empty mutable array to store your player instances:
NSMutableArray *playersArray = [[NSMutableArray alloc] init];
Loop through your loaded array, creating Player instances and adding them to your mutable array
for (NSDictionary *dictionary in loadedArray) {
Player *player = [[Player alloc] init];
player.name = dictionary[#"Name"];
player.highscore = dictionary[#"Highscore"];
[playersArray addObject:player];
}
Note: Ideally you want a initialiser method in your player, like this:
- (instancetype)initWithName:(NSString *)name highscore:(NSNumber *)highscore;
I have a JSON request getting this:
bills = (
{
id = 1;
name = "Cursus Nibh Venenatis";
value = "875.24";
},
{
id = 2;
name = "Elit Fusce";
value = "254.02";
}
);
I'm creating a NSDictionary for it.
I'm using JSONKit and I wanna know how can I populate my UITableView with this values? Thanks for any help!
EDIT
NSLog(#"my dictionary = %#", resultsDictionary);
my dictionary = {
bills = (
{
id = 1;
name = "Cursus Nibh Venenatis";
value = "875.24";
},
{
id = 2;
name = "Elit Fusce";
value = "254.02";
}
);
}
It looks like your bills dictionary is composed of an array of smaller dictionaries. You'd access it like this;
get the top Dictionary bills.
access each dictionary inside (for loop, etc) and create an array
load table view data from previously created array
Edit*
NSDictionary *billsDictionary = [NSDictionary dictionaryWithDictionary:[resultsDictionary objectForKey:bills]];
NSMutableArray *dataSource = [[NSMutableArray alloc]init]; //make this an ivar and your tabelView's data source.
for(NSDictionary *dict in billsDictionary){
[dataSource addObject:dict];
}
[tableView reloadData];
//then in your tableView cell
cell.textLabel.text = [[NSString stringWithFormat:#"%#", [[dataSource objectAtIndex:indexPath.row]objectForKey:#"name"]]
//Repeat for whatever else you want to add to the cell (subtitle, image, etc.) Hope this helps.
It seems like In the result dictionary, you are having an Array. Where each object in your Array is a dictionary. Tryout the following code.
NSArray *billsArray = [resultsDictionary objectForKey:#"bills"];
give [[billsArray objectAtIndex:indexPath.row] objectForKey:#"name"] in your tableView datasource method tableView: cellForRowAtIndexPath:
This is the code which i am using:
NSDictionary *errorInfo=nil;
NSString *source=#"tell application \"Mail\"\nget name of mailbox of every account\nend tell";
NSAppleScript *run = [[NSAppleScript alloc] initWithSource:source];
NSAppleEventDescriptor *aDescriptor=[[NSAppleEventDescriptor alloc]init];
aDescriptor=[run executeAndReturnError:&errorInfo];
[aDescriptor coerceToDescriptorType:'utxt'];
NSLog(#"result:%#",[aDescriptor stringValue]);
Output which i got:
result:(null)
Please help me anyone on this.Thanks in advance:)
IIRC that will return a list descriptor filled with list descriptors. You need to iterate over them and pull out the info you want. You're also initializing a descriptor and then immediately overwriting its pointer. Do something like (untested):
NSDictionary *errorInfo = nil;
NSString *source = #"tell application \"Mail\"\nget name of mailbox of every account\nend tell";
NSAppleScript *run = [[NSAppleScript alloc] initWithSource:source];
NSAppleEventDescriptor *aDescriptor = [run executeAndReturnError:&errorInfo];
NSInteger num = [aDescriptor numberOfItems];
// Apple event descriptor list indexes are one-based!
for (NSInteger idx = 1; idx <= num; ++idx) {
NSAppleEventDescriptor *innerListDescriptor = [aDescriptor descriptorAtIndex:idx];
NSInteger innerNum = [innerListDescriptor numberOfItems];
for (NSInteger innerIdx = 1; innerIdx <= innerNum; ++innerIdx) {
NSString *str = [[innerListDescriptor descriptorAtIndex:innerIdx] stringValue];
// Do something with str here
}
}
Swift version, tested in 2022:
func run(appleScript: String) {
var error: NSDictionary? = nil
if let scriptObject = NSAppleScript(source: appleScript) {
let output = scriptObject.executeAndReturnError(&error)
// Print All Values
let numberOfItems = output.numberOfItems
print("numberOfItems: \(numberOfItems)")
for i in 0..<numberOfItems {
let innerDescriptor = output.atIndex(i)
print("\(i): " + (innerDescriptor?.stringValue ?? "nil"))
}
// Catch Error
if let error = error {
print("Error: '\(error)'")
}
} else {
print("Error: Unable to init NSAppleScript")
}
}