How to get a value from dictionary which is inside an array? - ios

I want to store a message - "hi this is John KL", in some string, how to parse following example.
[
{
"message": "hi this is John KL"
}
]

Swift:
guard let anArray = input as? [[String:String]],
let message = anArray.first["message"] else {
print("unable to fetch data"
}
Objective-C:
- (void) readJSON {
NSError *result;
NSURL *url = [[NSBundle mainBundle] URLForResource: #"sample"
withExtension: #"JSON"];
NSData *data = [NSData dataWithContentsOfURL: url
options: 0
error: &result];
if (result != nil) {
NSLog(#"Error reading file: %#", result);
return;
}
NSArray<NSDictionary<NSString*, NSString*> *> *array = [NSJSONSerialization JSONObjectWithData: data options: 0 error: &result];
if (result != nil) {
NSLog(#"Error converting JSON: %#", result);
return;
}
else {
NSLog(#"\nJSON data = \n%#", array);
if (array.count < 1) {
NSLog(#"Not enough elements in array");
return;
}
NSString *message = array[0][#"message"];
if (message == nil) {
NSLog(#"Unable to fetch message");
} else {
NSLog(#"Message = \"%#\"", message);
}
}
}
The above Objective-C code does not test to make sure the object read from the JSON file is the correct type. It will crash if it is not an array containing a dictionary with a string key and string value. For a production app you'll want to add code to type-check the data.

Swift
Assign your json array to a variable type of [String : String] or [String : Any] dictionary array. [String : Any] is most commonly used dictionary but according to your data it suites with [String : String]
if let array = [
{
“message” : “hi this is John KL”
}
] as [Any]
Now, get your json/dictionary from array using index value and then get string from json using json key.
if let dictionary = array.first as? [String : Any] {
if let stringMessage = dictionary["message"] as? String {
print("stringMessage - \(stringMessage)")
}
}
Objective-C
NSArray * array = [
{
“message” : “hi this is John KL”
}
];
NSDictionary * dictionary = (NSDictionary *)[array objectAtIndex: 0];
NSString * stringMessage = (NSString *)[dictionary valueForKey: "message"];
NSLog(#"stringMessage - %#",stringMessage);

You can try this answer.
NSArray *result = [json objectForKey:#"result"];
for(NSString *currenObject in result){
NSLog(#"%#",currenObject);
NSString *currentValue = [currenObject valueForKey:#"message"];
}
NSLog(#"%#",currentValue);

Related

How can I use NSJSONSerialization with special characters like "ñ"?

I'm using NSJSONSerialization to parse Google suggestions.
The query "f" returns these suggestions:
["f",["facebook","flipkart","fox news","forever 21","friv","fandango","fedex","fitbit","food near me","flights"]]
The parser works fine but when there are special characters like "ñ" for the query "fac":
["fac",["facebook","facebook search","fac","facebook app","facebook lite","facebook login","facebook logo","facebook messenger","facetime","facebook en español"]]
It throws an exception:
Error Domain=NSCocoaErrorDomain Code=3840 "Unable to convert data to string around character 139." UserInfo={NSDebugDescription=Unable to convert data to string around character 139.}
Any ideas? I tried all different reading options but none of them works.
#pragma mark -
- (void)request:(NSString *)text
{
NSMutableArray *items = [[NSMutableArray alloc] init];
NSString *query = [text stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *languageCode = [[NSLocale preferredLanguages] firstObject];
if (!languageCode) {
languageCode = #"en";
}
NSString *URLString = [NSString stringWithFormat:#"http://suggestqueries.google.com/complete/search?q=%#&client=firefox&hl=%#", query, languageCode];
NSError *downloadError = nil;
NSData *JSONData = [NSData dataWithContentsOfURL:[NSURL URLWithString:URLString] options:0 error:&downloadError];
if (!downloadError && JSONData) {
NSError *parseError = nil;
id object = [NSJSONSerialization JSONObjectWithData:JSONData options:NSJSONReadingMutableContainers error:&parseError];
if (!parseError && object) {
if ([object isKindOfClass:[NSArray class]]) {
NSArray *objects = (NSArray *)object;
NSArray *texts = [objects objectAtIndex:1];
for (NSString *text in texts) {
SNGoogleItem *item = [[SNGoogleItem alloc] initWithText:text];
[items addObject:item];
}
[_delegate google:self didRespondWithItems:items];
}
else {
[_delegate google:self didRespondWithItems:items];
}
}
else {
[_delegate google:self didRespondWithItems:items];
}
}
else {
[_delegate google:self didRespondWithItems:items];
}
}
JSONSerialization supports all the encodings in JSON spec, says Apple documentation.
You didn't provide much info about the encoding scheme of your data but I guess you use nonLossyASCII or something like that, which is not supported by JSONSerialization.
Here is how I convert data to/from JSON:
let rawString = "[[\"facebook en español\"]]"
// if I use String.Encoding.nonLossyASCII below, I get the error you are getting
let data = rawString.data(using: String.Encoding.utf8)
let dict = try! JSONSerialization.jsonObject(with: data!)
let convertedData = try! JSONSerialization.data(withJSONObject: dict)
let convertedString = String(data: convertedData, encoding: String.Encoding.utf8)!
// now convertedString contains "ñ" character
This will convert whatever encoding used to UTF8:
NSData *JSONData = [NSData dataWithContentsOfURL:[NSURL URLWithString:URLString] options:0 error:&downloadError];
NSString *convertedJSONString; BOOL usedLossyConversion;
[NSString stringEncodingForData:JSONData encodingOptions:0 convertedString:&convertedJSONString usedLossyConversion:&usedLossyConversion];
NSData *convertedJSONData = [convertedJSONString dataUsingEncoding:NSUTF8StringEncoding];
Now, it works!

Crashing app due to null string added to dictionary

func addSongToQueue(){
let post = [
"data": [
"QueueId": MyViewState.selectedQueId,
"track":[
[
"title":selectedTrack.title,
"stream_url": selectedTrack.stream_url,
"userName" : selectedTrack.userName,
"artWorkURL": selectedTrack.artWorkURL,
"userAvatar": selectedTrack.userAvatar,
"trackID" : selectedTrack.trackID,
"duration" : selectedTrack.duration
]]]
]
Tracks Getting Code :
-(instancetype) initWithDictionary: (NSDictionary*) SCTrackDict {
self = [self init];
if (self) {
self.title = SCTrackDict[#"title"];
self.stream_url = SCTrackDict[#"stream_url"];
self.userDict = SCTrackDict[#"user"];
self.userName = self.userDict[#"username"];
self.artWorkURL = SCTrackDict[#"artwork_url"];
self.trackID = SCTrackDict[#"id"];
self.userAvatar = self.userDict[#"avatar_url"];
self.duration = SCTrackDict[#"duration"];
}
return self;
}
Parsing Data into Tracks :
+(NSMutableArray *) parseJSONData: (NSData *) JSONData {
NSError* error;
NSMutableArray* SCTrackArray = [NSMutableArray new];
NSArray *JSONArray= [NSJSONSerialization JSONObjectWithData:JSONData options:0 error: &error];
if ([JSONArray isKindOfClass:[NSArray class]]) {
for (NSDictionary* trackDict in JSONArray) {
SCTrack* trackObject = [[SCTrack alloc]initWithDictionary:trackDict];
//Need to print out trackDict to see JSON dictionary
[SCTrackArray addObject:trackObject];
}
}
return SCTrackArray;
}
How can I add "" (empty string) if NSNull is there and also crashing on trackid as it is long value.
Is it possible to modify this code without checking individual key before adding in dict?
Clarify to yourself: What action do you want to take if a key that you expect is not present, or is [NSNull null], or is an empty string, or is a dictionary when you expected a string and so on and so on.
Once you've explained that to yourself, you write the code accordingly. It seems at the moment your code follows the rule "If it's not there, I'll crash".
before adding an object just check like this that is this null or not
if(yourObject isEqual:(id)[NSNUll null])
{
// Then do nothing
}
You can use something like this:
"stream_url": selectedTrack.stream_url != nul ? selectedTrack.stream_url : #"";
Hope it help.
You can read about Ternary operation

Get NSString as NSArray from NSDictionary

I've the following data in NSDictionary for an object field_names that has below value.
{dBur0z9,nr8r0,R0ru,jrurw,qB5rz9ry},{gr2,Z5uzr,Rwxyr5z0Ar5},^~gr2~cry69v~br9rtyz~Z03r4rsru^~Z5uzr~Uvy3z~dB4srz^5B33,(),9ruI,evD3rsv3,,HLK,evDsBAA65,evDtyvt2s6E,5B33,5B33,5B33,5B33,{6ww},SRiTfUV,5B33,5B33,5B33,5B33
I'm trying to get it as NSArray. I tried
`NSArray *array = [dictionary objectForKey:#"field_name"];
But that returns an NSString not an NSArray. Then I tried to replace { } with [ ] and appended [ ] to make it json array,
NSString *s =[[dictionary objectForKey:#"field_names"] stringByReplacingOccurrencesOfString:#"{" withString:#"["];
s = [s stringByReplacingOccurrencesOfString:#"}" withString:#"]"];
s= [NSString stringWithFormat:#"[%#]",s];
NSDictionary *temp = #{#"array":s };
NSLog(#"%#", [temp objectForKey:#"array"]);
But still I'm getting it as NSString
[[dBur0z9,nr8r0,R0ru,jrurw,qB5rz9ry],[gr2,Z5uzr,Rwxyr5z0Ar5],^~gr2~cry69v~br9rtyz~Z03r4rsru^~Z5uzr~Uvy3z~dB4srz^5B33,(),9ruI,evD3rsv3,,HLK,evDsBAA65,evDtyvt2s6E,5B33,5B33,5B33,5B33,[6ww],SRiTfUV,5B33,5B33,5B33,5B33]
Please help me getting it NSArray!
You're getting it as a string because it is in fact string. I feel like you're trying to parse it as a JSON string??
If so, you first need to have that string in a valid JSON format. Here's an example JSON
{
   "AnArray": [
"string 1",
      "string 2",
      "string 3"
   ]
}
(without the line breaks of course I just added them for readability)
Once you have it as a valid JSON formatted string, you can do this
NSError *error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData: [dictionary[#"field_names"] dataUsingEncoding:NSUTF8StringEncoding] options: NSJSONReadingMutableContainers error: &error];
NSArray* YourArray = json[#"AnArray"];
I didn't find any cocoa method for this task, so I replaced , with & that occurs within {} and then used [string componentsSeparatedByString:#","] method to get it as NSArray. Below is the code
-(NSString *)prepareFields:(NSString *)string {
NSString *remainingString =string;
NSString *newString = #"";
#try {
while ([remainingString rangeOfString:#"{"].location != NSNotFound ) {
NSUInteger from = [remainingString rangeOfString:#"{"].location ,
to =[remainingString rangeOfString:#"}"].location+1 ;
NSString *part = [[remainingString substringWithRange:NSMakeRange(from,to)] stringByReplacingOccurrencesOfString:#"," withString:#"&"];
remainingString = [remainingString substringFromIndex:to];
if([newString isEqualToString:#""])
newString = [part substringWithRange:NSMakeRange([part rangeOfString:#"{"].location,[part rangeOfString:#"}"].location+1)];
newString = [NSString stringWithFormat:#"%#,%#",newString,[part substringWithRange:NSMakeRange([part rangeOfString:#"{"].location,[part rangeOfString:#"}"].location+1)]];
}
}
#catch (NSException *exception) {
NSLog(#"break %#" ,[exception reason]);
}
if([newString isEqualToString:#""])
newString = remainingString;
else
newString = [NSString stringWithFormat:#"%#,%#",newString,remainingString];
return newString;
}
And then called it
NSLog([[dictionary objectForKey:#"form"] componentsSeparatedByString:#","]);
That gave following array
(
"{dBur0z9&nr8r0&R0ru&jrurw&qB5rz9ry}",
"{dBur0z9&nr8r0&R0ru&jrurw&qB5rz9ry}",
"{gr2&Z5uzr&Rwxyr5z0Ar5}",
"",
"^~gr2~cry69v~br9rtyz~Z03r4rsru^~Z5uzr~Uvy3z~dB4srz^5B33",
"()",
9ruI,
evD3rsv3,
"",
HLK,
evDsBAA65,
evDtyvt2s6E,
5B33,
5B33,
5B33,
5B33,
"{6ww}",
SRiTfUV,
5B33,
5B33,
5B33,
5B33 )

XML into JSON conversion in iOS

I need to convert XML response to JSON and sand to the json To javaScript code.
My XML response:
<cell>
<Result>True</Result>
<sguid>02291c402-2220-422b-b199-f92f22e56d2f</sguid>
</cell>
I am using XMLReader supporting file from this site:
XMLReader
I am using this code to convert XML to JSON :
+ (NSString*) XMLToJson:(CXMLDocument *)xmlDocument
{
NSError *error = nil;
NSArray *resultNodes = [xmlDocument nodesForXPath:#"//cell" error:&error];
if(error)
NSLog(#"%#",error.description);
CXMLNode *cellNode = [resultNodes objectAtIndex:0];
NSLog(#"%#",cellNode.XMLString);
NSError *parseError = nil;
NSDictionary *xmlDictionary = [XMLReader dictionaryForXMLString:cellNode.XMLString error:&parseError];
NSLog(#"%#", xmlDictionary);
//{print this.
// cell = {
// Result = {
// text = True;
// };
// sguid = {
// text = "0391c402-1120-460b-b199-f92fffe56d2f";
// };
// };
//}
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:xmlDictionary
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
if(error)
NSLog(#"%#",error.description);
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"%#", jsonString);
return jsonString;
}
I got JSON response like this:
{
"cell" : {
"Result" : {
"text" : "True"
},
"sguid" : {
"text" : "0391c402-1120-460b-b199-f92fffe56d2f"
}
}
}
I need JSON response like this:
{
"cell": {
"Result": "True",
"sguid": "02291c402-2220-422b-b199-f92f22e56d2f"
}
}
Because then I send this json to javascript code I get that exception jquery mobile dont know parser this and throws an exception of syntax error.
I've seen programmers use this solution and is helping them but I still get the same result in this solution.
XML into JSON conversion in iOS
thanks
I just wrote a function for your problem, I tried it on with a couple of XMLs. Let me know if you find any issues
- (NSMutableDictionary *)extractXML:(NSMutableDictionary *)XMLDictionary
{
for (NSString *key in [XMLDictionary allKeys]) {
// get the current object for this key
id object = [XMLDictionary objectForKey:key];
if ([object isKindOfClass:[NSDictionary class]]) {
if ([[object allKeys] count] == 1 &&
[[[object allKeys] objectAtIndex:0] isEqualToString:#"text"] &&
![[object objectForKey:#"text"] isKindOfClass:[NSDictionary class]]) {
// this means the object has the key "text" and has no node
// or array (for multiple values) attached to it.
[XMLDictionary setObject:[object objectForKey:#"text"] forKey:key];
}
else {
// go deeper
[self extractXML:object];
}
}
else if ([object isKindOfClass:[NSArray class]]) {
// this is an array of dictionaries, iterate
for (id inArrayObject in (NSArray *)object) {
if ([inArrayObject isKindOfClass:[NSDictionary class]]) {
// if this is a dictionary, go deeper
[self extractXML:inArrayObject];
}
}
}
}
return XMLDictionary;
}
And use it like this
NSDictionary *clearXML = [[self extractXML:[yourParsedXMLDictionary mutableCopy]] copy];
Your problem in using XMLReader. For resolve this problem you can use XMLConverter instead of the XMLReader.

How should I read the data from a json string? iphone

I have in a NSString "[{"van" : 1,312, "vuan":12,123}] and in order to get this values for every key, I am doing this:
NSData *data1 = [jsonResponse1 dataUsingEncoding:NSUTF8StringEncoding];
jsonArray = [NSJSONSerialization JSONObjectWithData:data1 options:kNilOptions error:&err];
self.van = [NSMutableArray arrayWithCapacity:1];
self.vuan = [NSMutableArray arrayWithCapacity:1];
for (NSDictionary *json in jsonArray) {
NSString * value = [json objectForKey:#"van"];
[self.van addObject:value];
lbl1.text = value;
NSString * value1 = [json objectForKey:#"vuan"];
[self.vuan addObject:value1];
lbl4.text = value1;
}
May be I don't have to use an array and instead to convert the NSData directly in a NSDictionary.
Anyway, I don't understand why jsonArray is nil, although jsonResponse1 contains the values I have written above.
EDIT: My boss have written the json string wrong. Thank you all for your suggestions!:)
Your JSON is invalid. Fix it. This site is your friend.
http://jsonlint.com/
You need to code more defensively and you need to report errors as they are found.
Firstly check if the JSON parsing failed and if so report the error:
NSData *data1 = [jsonResponse1 dataUsingEncoding:NSUTF8StringEncoding];
jsonArray = [NSJSONSerialization JSONObjectWithData:data1 options:kNilOptions error:&err];
if (jsonArray == nil)
{
NSLog(#"Failed to parse JSON: %#", [err localizedDescription]);
return;
}
Secondly if those keys are not in the JSON, objectForKey: will return nil and when you attempt to add that to the arrays, it will throw an exception, which is something you want to avoid:
for (NSDictionary *json in jsonArray) {
NSString * value = [json objectForKey:#"van"];
if (value != nil)
{
[self.van addObject:value];
lbl1.text = value;
}
else
{
NSLog(#"No 'van' key in JSON");
}
NSString * value1 = [json objectForKey:#"vuan"];
if (value1 != nil)
{
[self.vuan addObject:value1];
lbl4.text = value1;
}
else
{
NSLog(#"No 'vuan' key in JSON");
}
}
So in summary: runtime errors will occur so you need to ensure you handle them. When they occur you need to report them with as much information possible so that you can diagnose and fix them.

Resources