recursively parse json in javascript to retrieve certain keys' values - javascript

I am new to javascript and every time i try learning it, I just end up in an immense amount of frustration and disgust ! No offense, but this is my opinion or perhaps I am too stupid to not understand how it works at all.
I have a simple requirement. I have a pretty deeply nested dictionary (which is what it is called in many backend languages) at hand. To be more specific it is the raw text of a postman collection. The collection itself could have multiple nested directories.
Now all I want to do is to be able to parse this dictionary and do something with it recursively.
For example, if I had to do the same in python I would do it as simply as :
def createRequests(self, dic):
total_reqs = 0
headers = {}
print type(dic)
keys = dic.keys()
if 'item' in keys:
print "Folder Found. Checking for Indivisual request inside current folder . . \n"
self.item_list = dic.get('item')
for each_item in self.item_list:
self.folder.append(self.createRequests(each_item))
else:
print "Found Indivisual request. Appending. . . \n"
temp_list = []
temp_list.append(dic)
self.requestList.append(temp_list)
return self.requestList
where dic would be my dictionary that I want to parse.
Is there any simple and straight forward way to do the same in Javascript?
Let's just say all I want to do is that if I have a text file that has properly formed json data in it and whose contents have been read into dataReadFromFile and then it has been converted into a JSON as :
var obj = JSON.parse(dataReadFromFile);
is there any simple and easy way to convert this JSON to dictionary or the dataReadFromFile directly into a dictionary such that I can say something like dictioanry.keys() if I wanted a list of the keys in it.
Note that the content of the file is not fixed. It may have multiple levels of nesting, which may not be known beforehand.

Related

Scrapy: Converting Javascript array to Json on Python

I have been struggling with a site I am scrapping using scrappy.
This site, returns a series of Javascript variables (array) with the products data.
Example:
datos[0] = ["12345","3M YELLOW CAT5E CABLE","6.81","1","A","N","N","N","N","N",0,0,0,0,0,"0","0","0","0","0","P","001-0030","12","40K8957","28396","250","Due: 30-12-1899",0.0000,1,"",\'\'];
datos[1] = ["12346","3M GREEN CAT5E CABLE","7.81","1","A","N","N","N","N","N",0,0,0,0,0,"0","0","0","0","0","P","001-0030","12","40K8957","28396","250","Due: 30-12-1899",0.0000,1,"",\'\'];
...
So on...
Fetching the array into a string with scrapy was easy, since the site response prints the variables.
The problem is I want to transform it into Json so I can process it and store it in a database table.
Normally I would use Javascript's function Json.stringify to convert it to Json and post it in PHP.
However when using Python's json.loads and even StringIO I am unable to load the array into json.
Probably is a format error, but I am unable to identify it, since I am not expert in Json nor Python.
EDIT:
I just realize since scrapy is unable to execute Javascript probably the main issue is that the data is just a string. I should format it into a Json format.
Any help is more than welcome.
Thank you.
If you wanted to take an array and create a json object, you could do something like this.
values = ["12345","3M YELLOW CAT5E CABLE","6.81","1","A","N","N","N","N","N",0,0,0,0,0,"0","0","0","0","0","P","001-0030","12","40K8957","28396","250","Due: 30-12-1899",0.0000,1]
keys = [x for x in range(len(values))]
d = dict(zip(keys, values))
x = json.dumps(d)
There is a section in the scrapy doc to find various ways to parse the JavaScript code. For your case, if you just need to have it in an array, you can use the regex to get the data.
Since the website you are scraping is not present in the question, I am assuming this would be a more straightforward way to get it, but you could use whichever way seems suitable.

Javascript array/object order from associative PHP array

Before I describe the issue, please forgive any incorrect terms and accidental references to objects instead of arrays and vice-versa, I'm not completely up to speed on this but working my way through it.
I have the following array in PHP saved as a session variable:
{"CategoryF":[],"CategoryA":["Life","There","People","Land","Family"],"CategoryC":["Various"]}
After a thumbnail in a grid of images is dragged into a new order, it execute a function in javascript and makes a call to a PHP script using ajax. It currently only retrieves the most up to date version of a session array. It will later progress to make the necessary steps to save the updated array back to session variable and database:
var sorty = Sortable.create(thumbcontainer, {
animation: 250,
draggable: "img",
dataIdAttr: 'id',
onUpdate: function (/**Event*/evt) {
var orderList = sorty.toArray();
var catsArray =
$.ajax({
type: 'POST',
url: 'includes/proc_cats.php',
dataType: 'json'
}).done(function(returnedCatsArray) {
console.log(returnedCatsArray);
});
console.log('Dragged. Order is: ' + orderList);
}
});
proc_cats.php
<?php
// Access the existing session
session_start();
// $catsArray is a session variable, in the format as above.
$catsArray = json_encode($_SESSION['categoriesPics']);
echo $catsArray;
?>
The var orderList will produce a string with the order of each thumbnail by id, separated by comma: '42,35,95,12,57'.
The console shows the PHP array as a javascript array fine but in a different order. I want to be able to insert the string containing the orders into the array and save it back into the database. It will associate with its relevant category, similar to:
{"CategoryF":[],"CategoryA":["Life":["23,74,47,12,86,83,12"],"There","People","Land","Family"],"CategoryC":["Various"]}
But can't lose the order as other parts of the site reference the array by indices using array_keys. The console produces:
Object:
CategoryA:Array[0]
CategoryC:Array[0]
CategoryF:Array[5]
Have I missed something? I believe that the overall array is an object rather than an array because it didn't have any index whereas the subcategories did and they get presented as an array. array_keys in PHP have made it straightforward enough to work around any indexing problems up until now on the PHP side in other areas of the site but I'm wondering if the solution for the javascript side is something as straightforward? The subcategories currently have indices only because I've yet to associate and orderList with them so I'm not trying not to backtrack and build an index for the array as it's going to get difficult (unless there's a simple way to do this that I've overlooked).
(This is a more specific version of a question I asked an hour ago that I've now deleted for being too broad).
I believe you have a slight confusion based on the terms 'associative array' and 'array'. A php associative array corresponds to a javascript object. returnedCatsArray should be accessed similar to $catsArray. ie. with keys. If one of those keys returns an an actual array, you can then index into it.
php array_keys would be Object.keys(returnedCatsArray) in javascript.
From further research it appears this is just not doable. So the best way to do this may be to provide an order array alongside my category array.
If I add the additional code of:
$parentCatOrder = array_keys($catsArray);
in my proc_cats.php script I have a concise way of generating an index reference for my original array on the fly each time. This produces an array similar to:
$parentCatOrder = {'categoryF', 'categoryA', 'categoryC'};
which has an index that I can refer to that keeps its order. So $parentCatOrder[2] will always produce 'categoryC' unless I've changed the array myself.
I then return both arrays to javascript using the following:
$return_data['catsarray'] = $catsArray;
$return_data['parentcatsorder'] = $parentCatOrder;
// Encode it back into a JSON object before sending
echo json_encode($return_data);
In javascript I can reference returnedCatsArray.catsarray[returnedCatsArray.parentcatsorder[1]][3] if I'm working with an index of 1-3 and guarantee this will produce the same result for every user unless the array has been changed by the user.

Get Data from Text File to Multidimensional Array Javascript

I have a little bit of an issue with a JavaScript function that needs to read data from a TextFile (something JS is already limited with) and then process tha TextFile data into a MultiDimensional Array (another thing that JS doesn't nativelly suport).
With that in mind, I have a text file in this format:
1, Name, Data, Serial
2, Name, Data, Serial
3, Name, Data, Serial
And so on.
So, the objective is to get that same data and put it, like that, into an array.
I suppose that, from what I've been reading, I need an Array of an Array, segmenting the first one by lines [/n] and the second one by commas [,]. However, given the "by-default" limitations, I'm very confused at this point. I do suppose I need jQuery, however.
I tried this:
var fs = require('fs');
var array = fs.readFileSync('file.txt').toString().split("\n");
for(i in array) {
var array = fs.readFileSync('file.txt').toString().split(",");
for(f in array) {
}
}
With little success, because then I don't really know how to store it, the objective being a Multidimensional Array that Replicates the Format of the text file, so latter it could be used to search by index or instance following an user input to get results.
I really appreciate any help.
At first glance it seems like you are trying to read in a CSV file. If that is indeed the case I recommend node-csv:
http://www.adaltas.com/projects/node-csv/
https://github.com/wdavidw/node-csv
This helped me reading file to JavaScript, however this example converts retrieved data to JSON. Just looking at the format of your text file, I would assume a JSON string or Javascript object would work with your data.
Example convert to JSON
With JSON and JS objects, instead of referencing a array indexes eg. array[i][x]. you would replace [x] with .propertyName
data = {
"id": 1,
"name": "Fred"
};
//access data like this
data[i].name //will return "Fred" as i =0
to create JS object, just initialize array properties without the ""(quotation marks). accessing JS and JSON properties are done in the same way, main advantage over a multidimensional array is that you can reference an actual property name, as opposed to indexes.

javascript array into object with same key names

I have an unusual problem to solve here. I have an array of Guids
[
"c01f8237-72c8-4fa6-9c53-1915750385aa",
"2c8a471b-c408-436c-81b1-3f3867d8ffb4",
"27a44d46-12bd-4784-ceed-57ada31b0e33"
]
This array has to be transformed into:
{
id: "c01f8237-72c8-4fa6-9c53-1915750385aa",
id: "2c8a471b-c408-436c-81b1-3f3867d8ffb4",
id: "27a44d46-12bd-4784-ceed-57ada31b0e33"
}
I know that shouldn't be done, but unfortunately cannot control the back end part. Any idea?
Thanks
The whole point of a dictionary key is that it uniquely maps to some value. Your desired output attempts to duplicate a key and therefore is neither possible nor does it make sense.
If you're passing this to a backend (as you suggest), then of course you can manually build a string to pass over the wire that duplicates keys in the payload, but you won't be able to actually do it in JavaScript first. You'll have to manually build the string.
Also note that you can call this format whatever you want, but you can't call it JSON and you can't use JSON libraries to build it (because it's not JSON). If your API expects a custom format, then you need to write code to build that custom format.
If all you want is a string just do something like
var str = '{' + idArray.map(function(id) {
return "id: "+id
}).join(',\n')+'}';
I have no idea what mime type you would put on that though since its not valid JSON.

How to parse JSON dynamically in iOS

We used a third party service and it provides a JS file.
The js file launches an http request and get a json.We parsed the json and got the content we wanted but the json format always changes.
Is there a way to parse the json but do not update our app?
It sounds awful stupid to constantly change schemas, but anyway, maybe you could try having a manifest somewhere in the cloud that translates the latest schema keywords into one your app understands?
Basically, I presume that the info in the JSON is similar (otherwise it wouldn't make sense at all) and only the keywords change. You could have a JSON you constantly update that translates the keywords used in the app into the newest one used by the webservice.
So an example would look like this. Imagine this is the format you are used to when developing the app (this is the one app expects).
{
"name" : "Henri",
"title" : "iOS Developer"
}
Now if the webservice changes it's schema and returns something like this
{
"key1" : "Henri",
"key2" : "iOS Developer"
}
You should have a manifest.json which translates it like this
{
"name" : "key1",
"title" : "key2"
}
I hope you get where I'm going with this, basically you can shift the translation to the cloud, giving you the chance to keep it up to date while app remains the same. So after loading in the translation you can access the data like this
NSString *name = [actualJSON objectForKey: [manifestJSON objectForKey: #"name"]];
The JSON home page has quite a bit of materials on the subject which should allow you to develop your own parser if you wish. There are also some ObjectiveC parsers available down at the bottom of the page.
http://www.json.org/
For this purpose we looked at Cocoa's standard key path infrastructure but weren't particularly happy with how it combines with arrays and dictionaries. In the end I ended up writing my own little key-path lookup thing, essentially like:
- (id)objectAtPath:(NSString *)path inObject:(id)object
{
// accept an input string like key1.key2.key3.index.key4.etc;
// so we'll split on the dots and use each separate component
// to navigate the object graph
NSString *components = [path componentsSeparatedByString:#"."];
for(NSString *component in components)
{
if([object isKindOfClass:[NSDictionary class]])
{
// if this is a dictionary, use this component as
// a key into the dictionary
object = [object objectForKey:component];
}
else
if([object isKindOfClass:[NSArray class]])
{
// if this is an array, use this component
// as an index into the array
NSInteger index = [component integerValue];
// treat out of bounds indices as finding nil
// rather than raising an exception
if(index < 0 || index >= [object count]) object = nil;
else object = [object objectAtIndex:index];
}
}
}
So you might call objectAtPath:#"shoes.4.typeOfLaces" inObject:jsonResult if 'jsonResult' is a dictionary to get the array 'shoes', the dictionary at index 4 in the array and then whatever value that dictionary has for the key 'typeOfLaces'.
The production code actually has some smarter navigation aids, allowing you to say things like "take whichever object in this array of dictionaries has the largest value for the key 'size'" or "take the object with type=large if it exists, otherwise take any object", but exactly what you want to do there will depend on your app and the variability of the schema.
Once you're navigating object graphs by key path, you can just grab the current key paths from a server somewhere, allowing you to change how JSON is navigated on device without submitting a new binary.
The only warning I'd add is to be careful how much functionality you put into your key paths. Apple don't allow fresh code to be downloaded so whatever you do you don't want to end up at anything that Apple could construe as a scripting language, no matter how restricted.

Categories

Resources