Accessing JSON objects from objects without titles in JQuery - javascript

I am receiving this JSON file back from an AJAX call:
[
{
"LINKNAME": "Annual Training",
"HITS": 1
},
{
"LINKNAME": "In Focus Newsletter",
"HITS": 1
},
{
"LINKNAME": "NITA (secured)",
"HITS": 1
},
{
"LINKNAME": "Your Current Events",
"HITS": 1
},
]
Here is my AJAX call:
$(document).ready(function(e) {
$.ajax({
method: "GET",
url: url,
}).done(function(api) {
console.log(api);
var obj = JSON.parse(api),
totRes = Object.keys(obj).length;
$.each(obj.children, function (index, value) {
alert(value);
});
}).fail(function( jqXHR, textStatus ) {
alert('Service Catalog: Error loading '+jqXHR+' data. Request fail caused by: '+textStatus);
});
});
I need to be able to extract the data from the JSON and use it but since the JSON objects aren't gioven a title then I am unsure how to extarpolate the data inside the inner object. Thanks in advance. Please ask if you do not understand my question.

Your JSON is just an array of plain objects.
To iterate over an array, you can use various methods. Since you're using jQuery, I'll just suggest $.each:
var arr = JSON.parse(api);
$.each(arr, function(i, obj) {
// access whatever property you want... obj[LINKNAME] or whatever
});
You can also use Array.prototype.forEach, or even just your basic for loop:
arr.forEach(function(obj) {
// obj is the current plain object... e.g. { LINKNAME: 'whatever', HITS: 0 }
});
I would also consider paying attention to how you are referring to the objects that you are receiving. While it is true that arrays are objects, and plain objects are objects, I would probably stick to referring to an array as an array, and a plain object as an object. This is because what you are receiving, in the form of JSON, is an array object of plain objects (or more simply, an array of objects).
Calling the array an "object" and referring to it as obj may confuse you when reading through the code quickly (yes, it is a good abstraction for potential extensibility if you end up not always receiving an array, but that's not the case here.)
Also, to once you have access the object in the each loop, you can iterate over the properties of the object if you need to (taken from this answer):
var obj = {
"a": 1,
"b": 2,
"c": 3
};
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
// or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
alert("prop: " + prop + " value: " + obj[prop])
}
}

First, you can add the setting dataType: 'json' when you send a request. This way you'll have api as javascript array.
Then you'll be able to iterate it via javascript for.
$.ajax({
method: "GET",
url: url,
dataType: "json"
}).done(function(api) {
for (var i = 0; i < api.length; i++) {
var name = api[i]["LINKNAME"],
hits = api[i]["HITS"];
// ...
}
// ...

$(document).ready(function(e) {
$.ajax({
method: "GET",
url: url,
}).done(function(api) {
if (api && api.length > 0) {
api.forEach(function (item) {
console.log(item); // logs whole object
console.log('item name %s', item.LINKNAME);
console.log('item hits %s', item.HITS);
});
}
}).fail(function( jqXHR, textStatus ) {
alert('Service Catalog: Error loading '+jqXHR+' data. Request fail caused by: '+textStatus);
});
});
You can filter the results to make sure you're only using objects that contain both 'LINKNAME' and 'HITS' pretty easily:
.done(function(api) {
if (api && api.length > 0) {
var objs = api.filter(function (item) {
return item.hasOwnProperty('LINKNAME') && item.hasOwnProperty('HITS');
});
objs.forEach(function (item) {
console.log(item); // logs whole object
console.log('item name %s', item.LINKNAME);
console.log('item hits %s', item.HITS);
});
}
});

Related

Ajax array transforming into associative array

So, I'm building an API in Ruby on Rails and I'm trying to force an array to be sent through ajax.
It seems quite an easy task if it wasn't for the fact that the array is being received as an associative array other than regular array!
Basically an array with objects like:
[
{
"shipping_id":"1",
"option":"1"
},
{
"shipping_id":"2",
"option":"2"
}
]
becomes:
{"0"=>{"shipment_id"=>"1", "option"=>"1"}, "1"=>{"shipment_id"=>"2", "option"=>"2"}}
instead of
[{"shipping_id"=>"1", "option"=>"1"}, {"shipping_id"=>"2", "option"=>"2"}]
This is the JS I'm using to test the API:
function select_shipping(){
obj1 = {
"shipment_id": "1",
"option": "1"
};
obj2 = {
"shipment_id": "2",
"option": "2"
};
var shipments = [obj1, obj2];
var payload = {
user_options: shipments
}
$.post('/shipping/calculate/select', // url
payload, // data to be submit
function(data, status, jqXHR) {// success callback
console.log(data);
})
}
How can I transform my payload to go as a regular array instead of associative?
You can do the following:
Note that this solution can process any number of shipments.
var shipments = [
{
"shipping_id":"1",
"option":"1"
},
{
"shipping_id":"2",
"option":"2"
}
]
var payload = {}
shipments.map(
function(shipment, index){
payload["$".concat(index)] = shipment;
}
);
console.log(payload);

Using array.push not giving correctly structured array (cant use array with filter function)

I'm using array.push to push the contents of a JSON response to an array. But when doing it, it adds some weird formating to my array. As a result, I cannot use the filter function to filter the array. I hard coded some json in another test case, and successfully used the filter function (see images below of comparisons of console.logs)
The JSON response looks like this:
{
"posts": [
{
"id": 1702574719019,
"title": "Title 1",
"published_at": "2019-02-16T09:40:36-05:00",
"created_at": "2019-02-16T09:40:37-05:00",
"updated_at": "2019-02-16T09:40:38-05:00",
"vendor": "DZR"
},
{
"id": 1702574719019,
"title": "Title 2",
"published_at": "2019-02-16T09:40:36-05:00",
"created_at": "2019-02-16T09:40:37-05:00",
"updated_at": "2019-02-16T09:40:38-05:00",
"vendor": "DZR"
}
]
}
How I handle this data looks like this (snippet from success ajax callback):
var this.postList = [];
var t = this;
while (i < pages) {
$.ajax({
url: "" + i,
dataType: 'json',
type: 'get',
success: function(data) {
$.each( data.posts, function( i, value ) {
t.postList.push( value );
});
},
error: function(XMLHttpRequest) {
}
});
i++;
}
This is how postList looks when I console.log it. The objects are not inside the Array [], like the image after this.
This is how I presume it should look, thus not letting me use array.filter correctly (returns nothing)
I believe I am using array.push incorrectly, and not correctly adding the objects to the array and therefore it looking weird when I console.log it. But I have no idea how to correct this, any info would be appreciated.
The this keyword you are using refers to the scope you're currently in. Thus, this refers to the callback called on $.each.
In order to push your values to postList, just use the following:
postList.push(...)
instead of
this.postList.push(...)
Don't use this in a callback.
You can do this by just
postList = data.posts;
If you use
$.each( data.posts, function( i, value ) {
postList.push( value );
});
without this. It works perfectly
Try with below code.
this.postList = [];
var t = this;
success: function(data) {
$.each( data.posts, function( i, value ) {
t.postList.push( value );
});
}
Here just define this.postList as array and then use it to push values.

How can I access a JS object property whose value is an unknown integer?

The JSON response returned from this wikipedia API call is a series of nested objects. To travel down the object property chain and access the text of interest, I have to first access a property whose value is a random number, dependent upon the wikipedia page I query by title.
An example for the page titled "San%20Francisco" (page id = 49728):
Object Property Chain:
responseJSON.wiki[0].query.pages[<<page id>>].extract
Example API Call: https://en.wikipedia.org/w/api.php/?origin=*&format=json&action=query&prop=extracts&exintro=&explaintext=&titles=San%20Francisco
Is there some way that I can identify the property whose value is a random integer? There is only one child of pages in the chain whose value is an integer. I cannot think of another solution and do not know of any JSON parsing method that would be effective.
I am inexperienced with AJAX requests and am making my ajax call in this way using jQuery. I would like to mention this in case I am doing something naive:
var getWiki = function (obj) {
return $.ajax({
url: "http://en.wikipedia.org/w/api.php" +
"?origin=*" + "&format=json" +
"&action=query" + "&prop=extracts" +
"&exintro=" + "&explaintext=" + "&titles=" +
obj.position,
method: 'GET'
});
};
Well, if there is always a single property on pages object then you can try either method:
if (typeof Object.values !== 'function') {
Object.values = obj => Object.keys(obj).map(key => obj[key]);
}
const responseJSON = {
"batchcomplete": "",
"query": {
"pages": {
"49728": {
"pageid": 49728,
"ns": 0,
"title": "San Francisco",
"extract": "Some text"
}
}
}
}
const pages = responseJSON.query.pages;
const extractedWithKeys = pages[Object.keys(pages)[0]];
const extractedObjValues = Object.values(pages)[0];
console.log(extractedWithKeys, extractedObjValues)
If your object has only a single key, you can get it using Object.keys(object)[0] and then perform a dynamic bracket-notation property access on the original object. (This is what the dig utility does in the example below.)
Also note that you can use .promise() to make handling your JSON response a bit tidier. I would suggest you add type: 'json' to your AJAX request, too, so that you don't have to parse the string data yourself.
function getWiki(obj) {
return $.ajax({
url: "http://en.wikipedia.org/w/api.php" +
"?origin=*" + "&format=json" +
"&action=query" + "&prop=extracts" +
"&exintro=" + "&explaintext=" + "&titles=" +
obj.position,
method: 'GET',
type: 'json'
}).promise()
}
function dig(object) {
return object[Object.keys(object)[0]]
}
getWiki({
position: 'San Francisco'
})
.then(function(json) {
console.log(
dig(json.query.pages).extract //=> 'San Francisco (SF) ...'
)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You can actually do this without Object.keys or other similar tricks if you add the indexpageids parameter to the query.
Example API call: https://en.wikipedia.org/w/api.php?action=query&format=json&prop=extracts&indexpageids=1&titles=San+Francisco&exintro=1&explaintext=1
Example JSON output:
{
"batchcomplete": "",
"query": {
"pageids": [
"49728"
],
"pages": {
"49728": {
"pageid": 49728,
"ns": 0,
"title": "San Francisco",
"extract": "San Francisco (initials SF) <snip>"
}
}
}
}
Then you can use something like data.query.pages[data.query.pageids[0]].extract to get the extract (although bear in mind that sometimes no pages may be returned, depending on what query you use).
Wikipedia's API sandbox is useful for discovering parameters like indexpageids - experimenting there is usually quicker than reading the docs.

Bootstrap-3-Typeahead getting right json key

I am useing this plugin for an ajax auto complete feature
https://github.com/bassjobsen/Bootstrap-3-Typeahead
the bootstrap-3 type. The code below is working but I do not know why it works. Specifically how the the process and response parameter work.
$(document).ready(function() {
$('#typeahead-input').typeahead({
autoSelect: true,
minLength: 1,
delay: 400,
source: function (query, process) {
$.ajax({
url: '/api/location',
data: {sstr: query},
dataType: 'json'
})
.done(function(response) {
// console.log(response)
return process(response);
});
}
});
});
my json looks like this
[
{
"id": "123",
"name": "Frederiksted",
"state": "VI",
"zip_code": "840"
}
]
What if i wanted to autocomplete to populated based on on the zip_code field how would i do it?
I have tried doing "response.zipcode" but it comes out as undefined
First, response.zipcode will be undefined because response is a Array not a Object. You access zipcode by response[0].zip_code ( And also note that your property name is not 'zipcode' it is 'zip_code' ).
Second, documentation of the "source" property says: The data source to query against. May be an array of strings, an array of JSON object with a name property or a function.
So, what you give to the "process" method most probably should be a array of strings or array of JSON objects where each JSON object has a "name" property.
If your response is correct and returns an array of objects like you say,
then it means your objects each have a 'name' property,so that property is displayed. If you want to display something else, you need to create a new String array from the response:
So I would try this:
.done(function(response) {
// get the response and create a new array of Strings
var names = $.map (response, function(item) {
return item.name + '-' + item.zip_code;
});
// console.log(response)
return process(names);
});
or another way:
.done(function(response) {
// get the response and change the 'name' of each object
$.each (response, function() {
this.name = this.name + '-' + this.zip_code;
});
// console.log(response)
return process(response);
});
I think you have issue with json format:
[
"id": "123",
"name": "Frederiksted",
"state": "VI",
"zip_code": "840"
]

Manipulate ajax response

I have a ajax post method. I get an object from the backend
$.ajax({
type: "POST",
url: URL_one,
data: submitData
}).then(function (response) {
console.log("Ajax response", response);
});
and when i do a console.log(response); inside the post method, i see the following data.
>Object{Info:Array[200]}
>Info:Array[200]
>[0-99]
>0:Object
name:'Ashley'
on_pay: true
valid:"0"
>[100-199]
So each array has objects like one mentioned above with name, on_pay and valid. I want to do the following
Since all on_pay values are true in my case, i need to convert it to false. Also valid has string of 0. I need to put all values as blank instead of 0.
Is it possible to do ?? Can someone please shed some light on these.
Considering the JSON structure that you show, following should work to change the on_pay value:
response.Info.forEach(function(item){
item.on_pay = false;
});
If I'm understanding your question correctly, response is an array of items. You want to keep those items intact, but turn the on_pay property false and valid to an empty string.
You can use Array::map() to transform each item.
/*jslint node:true*/
"use strict";
// I am assuming your response looks something like this
var response = {
Info: [
{
name: "Ashley",
on_pay: true,
valid: "0"
},
{
name: "Jim",
on_pay: true,
valid: "0"
},
{
name: "John",
on_pay: true,
valid: "0"
}
]
};
// This will produce a new variable that will hold the transformed Info array
var fixedResponseInfo = response.Info.map(function (item) {
item.on_pay = false;
item.valid = "";
return item;
});
// This will edit the response.Info array in place
response.Info.forEach(function (item) {
item.on_pay = false;
item.valid = "";
});
console.log(fixedResponseInfo);
console.log(response);
This will keep your original response variable and produce a new variable fixedResponseInfo that contains the transformed array. If you don't care whether data in response is changed, you can use Array::forEach() to iterate instead.

Categories

Resources