Decoding JSON with JSONKit gives error - iphone

I have the following JSON that validates as valid JSON..
{"flights":[{"flight":{"flightno":"BAW699","timestamp":"2011-03-22 07:06:02","route":"LOWW-EGLL"}},{"flight":{"flightno":"BAW706","timestamp":"2011-03-21 19:08:02","route":"EGLL-LOWW"}},{"flight":{"flightno":"BAW5MG","timestamp":"2011-03-21 16:33:02","route":"LEMG-EGLL"}},{"flight":{"flightno":"BAW3AG","timestamp":"2011-03-21 11:25:02","route":"EGLL-LEMG"}},{"flight":{"flightno":"BAW5EB","timestamp":"2011-03-20 19:18:02","route":"EGLL-LPPT"}},{"flight":{"flightno":"BA0489","timestamp":"2011-03-20 09:40:02","route":"LEBL-EGLL"}},{"flight":{"flightno":"BA0475","timestamp":"2011-03-19 16:51:02","route":"LEBL-EGLL"}},{"flight":{"flightno":"BAW489","timestamp":"2011-03-18 08:08:02","route":"LEBL-EGLL"}},{"flight":{"flightno":"BA0799","timestamp":"2011-03-17 18:37:02","route":"EGLL>EFHK"}},{"flight":{"flightno":"BAW799","timestamp":"2011-03-17 16:31:01","route":"EFHK-EGLL"}},{"flight":{"flightno":"BAW794","timestamp":"2011-03-17 11:55:02","route":"EGLL-EFHK"}},{"flight":{"flightno":"GEUUZ","timestamp":"2011-03-17 09:43:02","route":""}},{"flight":{"flightno":"BAW487","timestamp":"2011-03-16 19:32:01","route":"LEBL-EGLL"}},{"flight":{"flightno":"BAW486","timestamp":"2011-03-16 16:57:02","route":"EGLL-LEBL"}},{"flight":{"flightno":"BAW459","timestamp":"2011-03-16 14:10:01","route":"LEMD-EGLL"}},{"flight":{"flightno":"BAW41LM","timestamp":"2011-03-16 10:09:02","route":"EGLL-LEMD"}},{"flight":{"flightno":"BA0795","timestamp":"2011-03-16 08:27:02","route":""}},{"flight":{"flightno":"BAW795","timestamp":"2011-03-16 07:01:02","route":"EFHK-EGLL"}},{"flight":{"flightno":"BAW798","timestamp":"2011-03-15 18:23:02","route":"EGLL-EFHK"}},{"flight":{"flightno":"BAW701","timestamp":"2011-03-15 14:24:01","route":"LOWW-EGLL"}},{"flight":{"flightno":"BAW700","timestamp":"2011-03-15 11:04:01","route":"EGLL-LOWW"}},{"flight":{"flightno":"BAW68BL","timestamp":"2011-03-15 08:14:01","route":"LEBL-EGLL"}},{"flight":{"flightno":"BAW82BL","timestamp":"2011-03-14 18:40:03","route":"EGLL-LEBL"}},{"flight":{"flightno":"BAW849","timestamp":"2011-03-14 08:15:02","route":"EPWA-EGLL"}},{"flight":{"flightno":"BAW40CB","timestamp":"2011-03-13 19:30:03","route":"EGLL-LEBL"}},{"flight":{"flightno":"BAW475","timestamp":"2011-03-13 15:30:02","route":"LEBL-EGLL"}},{"flight":{"flightno":"z.NO-FLIGHTNO","timestamp":"2011-03-13 13:00:03","route":""}},{"flight":{"flightno":"BAW474","timestamp":"2011-03-13 12:00:03","route":"EGLL-LEBL"}},{"flight":{"flightno":"BAW4WP","timestamp":"2011-03-13 08:45:02","route":"LPPT-EGLL"}}]}
I then try and parse this using JSONKit but can only get as far down as "flights" I cannot seem to access the "flight" object.
When I do the following
-(void)parseJSON:(NSString *)jsonData{
NSDictionary *deserializedData = [jsonData objectFromJSONString];
for (id key in deserializedData) {
NSLog(#"key: %#, value: %#", key, [deserializedData objectForKey:key]);
}
}
Only the following is put out to the log....
key: flights, value: (
{
flight = {
flightno = BAW906N;
route = "EGLL-EDDF";
timestamp = "2011-03-24 08:38:02";
};
},
{
flight = {
flightno = BAW365;
route = "LFLL-EGLL";
timestamp = "2011-03-24 06:17:01";
};
},
{
flight = {
etc....
I want to be able to get down to each flight and at the moment am stuck!

Get an array of all flights like this:
NSArray *flights = [deserializedData valueForKeyPath:#"flights.flight"];

thats because you have an array of dictionairies in your dictionairy object, acces them like this:
for (NSDictionairy *flight in [deserializedData objectForKey:#"flights"]){
NSLog(#"flight object with route.: %#", [flight objectForKey:#"route"]);
}

Related

NSJSONSerialization - key names from array

I am parsing JSON data using objective-c.
The data is as follows:
{"parcels":{"12595884967":{"kj_number":"KJ6612636902","recipient":"Krzysztof Racki","courier":"3"}}}
I have an object "parcels" which has keys for packages. Now while I dont have a problem extracting this using JSONSerialization class, I am stuck figuring how to get a key name (i mean, how to read value 12595884967 from code).
Code:
if ( [ NSJSONSerialization isValidJSONObject:jsonObject ] ) {
// we are getting root element, the "parcels"
NSMutableSet* parcels = [ jsonObject mutableSetValueForKey:#"parcels" ];
// get array of NSDictionary*'ies
// in this example array has single NSDictionary* element with flds like "kj_number"
NSArray* array = [ parcels allObjects ];
for ( int i = 0 ; i < [ array count ] ; ++i ) {
NSObject* obj = [ array objectAtIndex: i ];
// the problem: how i get this dictionary KEY? string value of 12595884967
// how I should get it from code here?
// like: number = [ obj name ] or maybe [ obj keyName ]
if ( [ obj isKindOfClass:[ NSDictionary class ] ] ) {
// this always evaluates to true
// here we do reading attributes like kj_number, recipient etc
// and this works
}
}
}
for example in java it was:
JSONObject json = response.asJSONObject();
JSONObject parcels = json.getJSONObject( "parcels" );
#SuppressWarnings("unchecked")
Iterator<String> it = parcels.keys();
while ( it.hasNext() ) {
String key = it.next(); // value of 12595884967
Object value = parcel.getObject( key ); // JSONObject ref with data
}
A set doesn't store keys. You want to get a dictionary from the json.
NSDictionary* parcels = [jsonObject objectForKey:#"parcels"];
// get the keys
NSArray *keys = [parcels allKeys];
for (NSString *key in keys) {
NSDictionary *parcel = [parcels objectForKey:key];
// do something with parcel
}
Getting the keys in an array first is optional, you could iterate over the parcels dictionary directly: for (NSString *key in parcels) {.
I would propose to use a NSDictionary instead of NSMutableSet.
The NSDictionary has a method allKeys that will provide you with the requested data.

How do I load an array from values?

I'm sorry in advance for a newbie question. I've been working on this for days, and I'm having comprehension problems. I used sudzc to help connect to my web service. The example function only returns 1 result (the last one). How can I load all the results into an array so that I can find CSHR_NUM = 8? I'm not sure if there is a problem with:
- (void) GetCashiersHandler: (id) value
Any help would be greatly appreciated!
The sudzc logging returns (there are hundreds of entries, I cut it down):
<TC diffgr:id="TC1" msdata:rowOrder="0">
<CSHR_POS_NAME>JACKSON<CSHR_POS_NAME />
<CSHR_NUM>8</CSHR_NUM>
</TC>
<TC diffgr:id="TC2" msdata:rowOrder="1">
<CSHR_POS_NAME>ALISON</CSHR_POS_NAME>
<CSHR_NUM>464</CSHR_NUM>
</TC>
I use the example method of calling:
[service GetCashiers:self action:#selector(GetCashiersHandler];
// Handle the response from GetCashiers to get login in name.
- (void) GetCashiersHandler: (id) value
{
// Do something with the CXMLNode* result
CXMLNode *result = (CXMLNode*)value;
NSLog(#"I returned the value: %#", result);
}
NSLog Results:
I returned the value: {
GetCashiersResult = {
diffgram = {
NewDataSet = {
TC = {
"CSHR_NUM" = 464;
"CSHR_POS_NAME" = ALLISON;
};
};
};
schema = {
element = {
complexType = {
choice = {
element = {
complexType = {
sequence = {
element = 0;
};
};
};
};
};
};
};
};
}
NSMutableArray * myData = [[NSMutableArray alloc] initWithCapacity:5];
// loop over items to add and add them with
[myData addObject:myItem];

Json Parsing issue iOS : missing "

I got a big issue when trying to parse json data in xcode. I have actually tried with two different parser and it still returns me a wrong json. Could anyone help in that ?
The string to parse (called jsonResp) is equal to :
{
"error":false,
"errorMessage":null,
"debugMessage":null,
"count":1,
"list":"links",
"data":[
{
"date":"Jeudi \u00e0 00:00:00",
"type":"friend",
"picture":"http://graph.facebook.com/22222222/picture? type=square",
"name":"Etouda Gaudo",
"ink_id":"1",
"chat_id":"1",
"count":"1",
"last_message":"CoUcou"
}
]
}
the string to parse is equal to :
NSData *jsonData = [jsonResp dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
NSLog(#"dictionary %#", dictionary);
and then I got the following result for the NSLog of dictionary :
dictionary {
count = 1;
data = (
{
"chat_id" = 1;
count = 1;
date = "Jeudi \U00e0 00:00:00";
"ink_id" = 1;
"last_message" = CoUcou;
name = "Test name";
picture = "http://graph.facebook.com/22222222/picture?type=square";
type = friend;
}
);
debugMessage = "<null>";
error = 0;
errorMessage = "<null>";
list = links;
}
I can't figure out why the " are missing...
Does anyone have a solution.
Thanks in advance.
NSLog is just a print representation for developers to view, it is the result of the description method being called on a class instance. Quotes are only added where the item might be ambitious without them such as a string with an embedded space. To verify that the JSON was parsed correctly validate it with code.
You are deserializing the JSON into an NSDictionary, which doesn't have to have quotes around it's property names, unlike JSON. Your parser is working correctly, but the NSLog of an NSDictionary won't show up exactly the same as the original JSON would.

Retrieving the key name on AVMetadataItem for an AVAsset in iOS

I am trying to identify the different metadata items on a video on the iPad. So far I was able to successfully use the AVAsset libraries to find the file, and generate an array of AVMetadataItems using metadataForFormat:. Only iTunes and Quicktime User data formats were found in the file. The issue is now that I have that information, I have no way of identifying what is what. I intended to load a dictionary with the information, indexed by the metadata key, but using the key property of AVMetadataItem appears not to work correctly as if returns a number (debugger says its an NSCFNumber). Here is some sample code of what I am doing:
ALAssetRepresentation *representation = [[valAsset defaultRepresentation] retain];
NSURL *url = [representation url];
AVURLAsset *aAsset = [[AVURLAsset URLAssetWithURL:url options:nil] retain];
metaDataDict = [[NSMutableDictionary dictionary] retain];
NSArray *fmtmetadata = [aAsset metadataForFormat:#"com.apple.itunes"];
for (AVMetadataItem* meta in fmtmetadata)
{
[metaDataDict setObject:[meta stringValue]
forKey:[meta key]];
NSLog(#"metadata: key = %#", [meta key]);
}
This yields the following output in the debugger console:
metadata: key = -1452383891
metadata: key = -1452841618
metadata: key = 1684370275
metadata: key = 1818518899
metadata: key = 1937009003
metadata: key = -1453101708
Incidentally, changing the NSLog line to read:
NSLog(#"metadata: %#", meta);
gives us output like:
metadata: keySpace=itsk, key=desc, commonKey=(null), locale=(null), value=This is the Description of the Video, time={INVALID}, duration={INVALID}, extras={
dataType = 1;
}
Any help is greatly appreciated!
Looks like these keys are encoded ID3 tags:
1684370275 = 0x64657363 = {'d', 'e', 's', 'c'}
1818518899 = 0x6C646573 = {'l', 'd', 'e', 's'}
1937009003 = 0x7374696B = {'s', 't', 'i', 'k'}
etc.
You can use following extensions:
extension AVMetadataItem {
var keyString: String {
if key is NSString { return key as! String}
else if key is NSNumber {
var keyValue = (key as? NSNumber)?.uint32Value ?? 0
keyValue = CFSwapInt32BigToHost(keyValue)
let array = withUnsafeBytes(of: &keyValue) { Array($0) }
let string = String(decoding: array, as: UTF8.self)
return String(string.map {$0 == "�" ? "#" : $0 })
} else {
return "Unknown"
}
}
}
It can return strings like this:
keyString
Description
#alb
Album
aART
Album Artist
#ART
Artist
#gen
Gener
#nam
Title
#cmt
Comment
To use:
let albumMetaData: [AVMetadataItem] = AVMetadataItem.metadataItems(from: asset.metadata, filteredByIdentifier: .iTunesMetadataAlbum)
print(albumMetaData.first?.keyString) // #alb
Credit goes to:
Learning AV Foundation: A Hands-on Guide to Mastering the AVFoundation Framework (McCune, Bob)

Obj-C / iPhone: NSArray question

I have an array that looks like this when printed via NSLog:
{
response = "Valid";
updates = (
{
string = "test";
integer = 3493;
},
{
string = "test2";
integer = 55454;
}
);
start-index = 0;
My question is how I can loop through through the "updates" array so that I may print the values for each "string" respectively.
Should be an easy "for" loop or something?
Dave
Assuming you NSLogged data has a type of NSDictionary with name data.
NSArray *updates = [data objectForKey:#"updates"];
for (NSDictionary *update in updates) {
NSLog(#"Update: %# - %#", [update objectForKey:#"string"], [update objectForKey:#"integer"]);
}