Parsing JSON file using JSONKit - objective-c

I am constructing a tuning fork app. The fork should allow up to 12 preset pitches.
Moreover, I wish to allow the user to choose a theme. Each theme will load a set of presets (not necessary to use all of them).
My configuration file would look something like this*:
theme: "A3"
comment: "An octave below concert pitch (ie A4 440Hz)"
presets: {
A3 220Hz=220.0
}
// http://en.wikipedia.org/wiki/Guitar_tuning
theme: "Guitar Standard Tuning"
comment:"EADGBE using 12-TET tuning"
presets: {
E2=82.41
A2=110.00
D3=146.83
G3=196.00
B3=246.94
E4=329.63
}
theme: "Bass Guitar Standard Tuning"
comment: "EADG using 12-TET tuning"
presets: {
E1=41.204
A2=55.000
D3=73.416
G3=97.999
}
...which need to be extracted into some structure like this:
#class Preset
{
NSString* label;
double freq;
}
#class Theme
{
NSString* label;
NSMutableArray* presets;
}
NSMutableArray* themes;
How do I write my file using JSON? ( I would like to create a minimum of typing on the part of the user -- how succinct can I get it? Could someone give me an example for the first theme? )
And how do I parse it into the structures using https://github.com/johnezang/JSONKit?

Here's a valid JSON example based on your thoughts:
[
{
"name": "Guitar Standard Tuning",
"comment": "EADGBE using 12-TET tuning",
"presets": {
"E2": "82.41",
"A2": "110.00",
"D3": "146.83",
"G3": "196.00",
"B3": "246.94",
"E4": "329.63"
}
},
{
"name": "Bass Guitar Standard Tuning",
"comment": "EADG using 12-TET tuning",
"presets": {
"E1": "41.204",
"A1": "55.000",
"D2": "73.416",
"G2": "97.999"
}
}
]
Read a file and parse using JSONKit:
NSData* jsonData = [NSData dataWithContentsOfFile: path];
JSONDecoder* decoder = [[JSONDecoder alloc]
initWithParseOptions:JKParseOptionNone];
NSArray* json = [decoder objectWithData:jsonData];
After that, you'll have to iterate over the json variable using a for loop.

Using the parser in your question and assuming you have Simeon's string in an NSString variable. Here's how to parse it:
#import "JSONKit.h"
id parsedJSON = [myJSONString objectFromJSONString];
That will give you a hierarchy of arrays and dictionaries that you can walk to get your Preset and Theme objects. In the above case, you would get an array with two dictionaries each with a name, comment and presets key. The first two will have NSString values and the third (presets) will have a dictionary as it's value with the note name as keys and the frequencies as values (as NSString objects).

Related

Reduce duplications (save complicated transforms for later use) in VScode snippets

Is there a way to create custom variables inside a VScode snippet?
I have these kind of snippets where I create a singleton, based on the name of a file and a folder.
Here's the snippet:
"Service": {
"prefix": "singletonByPath",
"body": [
"class ${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/upcase}$2/g}${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g} {",
" $0",
"}",
"",
"export const ${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/downcase}$2/g}${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g} = new ${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/upcase}$2/g}${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g}();",
""
],
"description": "Create an exported singleton instance and a class based on the filename and path"
},
So, when the snippet is triggered in a path like: '..../customers/service.ts' You will have this result:
class CustomersService {
}
export const customersService = new CustomersService();
The problem is that I have duplications of long hard to read regexes, and I would like to extract them to variables (or mirrors without tab stops).
I would even prefer having these variables in a "snippet-global location" so that I can use them in multiple snippets.
Is it possible to somehow reduce these duplications?
There are a couple of things you can do to simplify your snippet. There is no built-in way to save "variables" of pre-defined snippet parts.
Here though is a simplification of your code:
"Service": {
"prefix": "singletonByPath",
"body": [
// "class ${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/upcase}$2/g}${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g} {",
"class ${1:${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/upcase}$2/g}}${2:${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g}} {",
-- --
" $0",
"}",
"",
// "export const ${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/downcase}$2/g}${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g} = new ${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/upcase}$2/g}${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g}();",
"export const ${1/(\\w+)/${1:/downcase}/}$2 = new $1$2();",
""
],
"description": "Create an exported singleton instance and a class based on the filename and path"
}
Note the use of $1:${TM_DIRECTORY...} and likewise ${2:${TM_FILENAME_BASE...}
This effectively sets $1 to the result of the TM_DIRECTORY transform and $2 to the result of the TM_FILENAME_BASE transform and those "variables" can be used elsewhere in the snippet by just referring to $1 and $2.
Those "variables" can even be transformed themselves as in the ${1/(\\w+)/${1:/downcase}/} transform in the last line.
The last line of your snippet then becomes simply:
"export const ${1/(\\w+)/${1:/downcase}/}$2 = new $1$2();",
You will have to tab a couple of times because those "variables" are now tabstops, and the last transform won't be completed until you do tabstop past it, but that is a small price to pay for such a simplification.
There are other simplifications to your snippet that aren't "variable-related":
"body": [
"class ${1:${TM_DIRECTORY/.*[\\/\\\\](.*)/${1:/capitalize}/}}${2:${TM_FILENAME_BASE/(.*)/${1:/capitalize}/}} {",
" $0",
"}",
"",
"export const ${1/(\\w+)/${1:/downcase}/g}$2 = new $1$2();",
""
],
You can use the capitalize transform. Also note that this last body works for Windows and linux path separators.

Using the Parse Template transformer with an array in the data

I'm a newbie to Mulesoft, and I'm looking to transform a Json object into an XML object via the Parse Template transformer. Straight forward enough, however, what is the appropriate approach when the Json object has an array with an undetermined number of elements?
For example, if I have a JSON object that looks like
{ "name" : "Methusela",
"hobbies: [
"name": "guitar",
"name": "cooking",
"name": "someting",
...
]}
where the number of hobbies is unknown at runtime
and my xml template looks like:
<Person>
<Name>#[payload.name]</Name>
<Hobbies>
<!- What should this bit look like -->
</Hobbies>
So - my question is how should I approach the conversion of the open ended JSON array to XML?
Note that we are currently exploring the community edition and therefore don't have access to the data mapping functionality available through the enterprise edition.
Thanks
Personally, to transform a Json object into an XML object, by using Community edition, I will use: JSON to Object and Object to XML transformers.
However, to transform it using Parse Template I will utilize Mule Expression Language (MEL). For example:
<Person>
<Name>#[json:name]</Name>
<Hobbies>
#[
org.json.JSONObject jsonObject = new org.json.JSONObject(payload.toString());
org.json.JSONArray jsonArray = jsonObject.get("hobbies");
String hobbies = "";
for(int i = 0; i < jsonArray.length(); i++) {
hobbies += "<Name>" + jsonArray.get(i).getString("name") + "</Name>";
}
hobbies;
]
</Hobbies>
</Person>
In parse template you can use simple javascript loop:
for(i=0;i<#[payload.Hobbies].length;i++){
document.getElementById('Id').innerHtml += #[payload.Hobbies][i]
}

Extra JSON value to display in Objective C

In my app, I get the following response for a failed user login:
{
"non_field_errors": [
"User account is disabled."
]
}
Is there a way to get this in Objective-C to only display: User account is disabled.?
When I do the following, it displays:
(
"User account is disabled."
)
Code:
NSLog(#"%#",[JSONValue objectForKey:#"non_field_errors"]);
How can I remove the parentheses and double quotes?
Parentheses is there because you are getting response in such a way. you can access your data using following way.
JSONValue[#"non_field_errors"][0] // This will return User account is disabled.
That is because the value for key non_field_errors is a JSON Array (Notice the square brackets). So use this :
NSArray *arr = [JSONValue objectForKey:#"non_field_errors"];
NSLog(#"%#",[arr firstObject]);
or just cram it all in one line
[(NSArray*)[JSONValue objectForKey:#"non_field_errors"] firstObject];

Json get a parameter can't access on it iOS

That's an example
{
"updated":1350213484,
"id":"http://www.google.com/reader/api/0/feed-finder?q\u003dProva\u0026output\u003djson",
"title":"Risultati di feed per \"Prova\"",
"self":[
{
"href":"http://www.google.com/reader/api/0/feed-finder?q\u003dProva\u0026output\u003djson"
}
],
"items":[
{
"title":"Home Page - La prova del cuoco",
"id":"http://www.laprovadelcuoco.rai.it/",
"updated":1350213485,
"feed":[
{
"href":"http://www.laprovadelcuoco.rai.it/dl/portali/site/page/Page-ffb545b4-9e72-41e5-866f-a465588c43fa-rss.html"
}
],
"alternate":[
{
"href":"http://www.laprovadelcuoco.rai.it/",
"type":"text/html"
}
],
"content":{
"direction":"ltr",
"content":"Diventa un cuoco provetto con “La Prova del Cuoco”: le videoricette in un' applicazione di facile e veloce consultazione per il tuo Iphone. Scopri come acquistare ..."
}
},
{
"title":"Le prove Invalsi di matematica e italiano",
"id":"http://online.scuola.zanichelli.it/quartaprova/",
"updated":1350213486,
"feed":[
{
"href":"http://online.scuola.zanichelli.it/quartaprova/feed/"
}
],
"alternate":[
{
"href":"http://online.scuola.zanichelli.it/quartaprova/",
"type":"text/html"
}
],
"content":{
"direction":"ltr",
"content":"Un sito Zanichelli dedicato alle prove Invalsi di italiano e matematica: esercitazioni, consigli, informazioni utili, novità, aggiornamenti e blog d'autore sulle prove ..."
}
},
How can I get the feed URL?
That's what I do
NSString *daParsare=[reader searchFeed:searchText];
NSArray *items = [[daParsare JSONValue] objectForKey:#"items"];
for (NSDictionary *item in items) {
NSString *title = [item objectForKey:#"title"];
NSString *feed = [item valueForKeyPath:#"feed.href"];
}
[tab reloadData];
With the title everything is ok but when I try to access to the feed paramater I get the error...
Assuming your JSON object is named jsonObject, you would simply access the href element. So, in your current object, the URL is in an object named href, which is the first (and in this case, only) element in an array named feed at the top level:
NSString* urlString = jsonObject[#"feed"][0][#"href"];
You should check to make sure that if feed exists, it's not an empty array before you access one of its elements.
NSString *feed = [item valueForKeyPath:#"feed.href"];
is wrong, as feed refers to an array, that again holds a dictionary.
NSString *feed = [[[item objectForKey:#"feed"] objectAtIndex:0] objectForKey:#"href"];
If you are using an modern Xcode, this last line is the same as in Jason Cocos answer.
NSString* feed = item[#"feed"][0][#"href"];
this syntax is called Object Subscription.

Is my jSON well written?

is my jSON well written ? i just have boxes with their detail and i want to populate a core data entity afterwards. (btw, i need a easy tutorial to set my datas in coredata, do you have? cimgf's tutorial is too complicated or i just don't understand them :/
{
"boxes": {
"boxesDetail": [
{
"codeArticle": "WPCDE01C412L",
"nameBox": "boxName",
"texteMarketing": "boxTextMarketing",
"descriptionBox": "boxDescritpion",
"nbActivities": 1650,
"kindBox": "boxKind",
"typeBox": "boxType",
"priceBox": 20,
"dlu": 2014,
"note": 3
},
{
"codeArticle": "BOOYAKA!!",
"nameBox": "boxNameName",
"texteMarketing": "boxTextMarketing",
"descriptionBox": "boxDescritpion",
"nbActivities": 1650,
"kindBox": "boxKind",
"typeBox": "boxType",
"priceBox": 39,
"dlu": 2014,
"note": 3
}
]
}
}
Just as JeremyP says, you should use a JSON Parser to check your JSON. I also fully recommend jsonlint.com for checking JSON.
As far as an easy tutorial for CoreData I would recommend Ray Wenderlich's tutorial. It's updated for iOS 5 so perhaps having an updated tutorial will help you understand. I haven't done the updated tutorial, but I'm pretty sure that's the one I looked at pre-iOS 5 when I was learning about CoreData.
After having a look at the CoreData tutorial and getting your head around it and understanding it, I would write a helper function as a category on your Box.
Something along the lines of
+ (id)boxWithDictionary:(NSDictionary *)dict withManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;
{
Box *box = [NSEntityDescription insertNewObjectForEntityForName:#"Box"
inManagedObjectContext:managedObjectContext];
box.codeArticle = [dict objectForKey:#"codeArticle"];
box.nameBox = [dict objectForKey:#"nameBox"];
box.texteMarketing = [dict objectForKey:#"texteMarketing"];
box.descriptionBox = [dict objectForKey:#"descriptionBox"];
box.nbActivities = [dict objectForKey:#"nbActivities"];
box.kindBox = [dict objectForKey:#"boxKind"];
box.typeBox = [dict objectForKey:#"boxType"];
box.priceBox = [dict objectForKey:#"priceBox"];
box.dlu = [dict objectForKey:#"dlu"];
box.note = [dict objectForKey:#"note"];
return box;
}
The reason to put this code in a category and in a separate file to the Box.m and Box.h files that Xcode generate is so that if you ever edit the Box entity in CoreData and have to generate a new file, it won't overwrite this category file with your helper function.
I hope this helps.