JSONParse array nested inside of callback lost the context [duplicate] - javascript

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 8 years ago.
I'm try to parse a object from response to web service, that has the following structure:
{ "idRonda":"1",
"puntos":{
"p1":{"id":1,"descripcion":"punto uno","tag":"0497e1b13e0280"},
"p2":{"id":2,"descripcion":"punto dos","tag":"0498e9b13e0280"},
"p4":{"id":4,"descripcion":"punto cuatro","tag":"04419092432f80"},
"p5":{"id":5,"descripcion":"punto cinco","tag":"0462f812b82a80"},
"p3":{"id":3,"descripcion":"punto tres","tag":"046cfd92432f80"}
}
}
So, I try to iterate over the "array" puntos, then I do the following:
//data has the response from web service
var json = JSON.parse(data);
var puntos = json.puntos; //until here it's ok
When I print the value and type of puntos :
console.log( " Puntos Object : "+ puntos );
console.log( " TypeOf : "+ Ember.typeOf(puntos) );
Output:
Puntos Object : [object Object]
TypeOf : string
My attempt:
for (var k in puntos)
{
// I thought that k must be "p1", "p2"..., but I'm wrong
if (puntos.hasOwnProperty(k))
{
var values = puntos[k];
var id = values['id'];
}
}
If I print the k value I get(I don't know what mean it):
key: 0
key: 1
.
.
.
key: 13
key: 14
key: fmt
key: w
key: loc
key: camelize
key: decamelize
key: dasherize
key: underscore
key: classify
key: capitalize
key: htmlSafe
Now how iterate over the puntos object to get id, descripcion and tag values?
UPDATE:
var puntos = json.puntos;
var db = window.sqlitePlugin.openDatabase("Rondas", "1.0", "Dev", -1);
db.transaction(function(tx)
{
tx.executeSql("SELECT * from Punto;", [], function(tx, res)
{
if( res.rows.length === 0)
{
for (var k in puntos)
{
if (puntos.hasOwnProperty(k))
{
var id = puntos[k].id;
var descripcion = puntos[k].descripcion;
var tag = puntos[k].tag;
console.log( "KEY: "+k+" ,ID: "+id + " ,DESCRIPCIƓN: "+descripcion+" ,TAG: "+tag );
}
}
}
}
}
The code above fail becase the object puntos lost the scope because it inside of a callback then then only solution is ensure the object context.
SOLUTION
db.transaction(function(tx)
{
//ensure the object context.
var points = puntos;
tx.executeSql("SELECT * from Punto;", [], function(tx, res)
{
if( res.rows.length === 0)
{
for (var k in points)
{
...
}
}
}
}

Using a for loop like this
for(key in puntos)
{
var id = puntos[key].id;
var descripcion= puntos[key].descripcion;
var tag = puntos[key].tag;
}

Related

Totalling/merging JavaScript values based on key

I have a JavaScript array which I use jQuery to display values in a table
for (var i = 0; i < data.MyArray.length; i++) {
$('#my-table').append('<tr><td>' + data.MyArray[i].DisplayGroup + '</td><td>' + data.MyArray[i].Value + '%<td></tr>');
}
I would like to "group" the values based on DisplayGroup prior to displaying the values
So if my array contains
DisplayGroup: ABC Value: 5
DisplayGroup: DEF Value: 3
DisplayGroup: ABC Value: 6
DisplayGroup: GHI Value: 2
I would like to total the duplicate DisplayGroup entries (in this example ABC) so that I display
ABC 11
DEF 3
GHI 2
Is there a way to iterate through the array and create a new array to then use?
var array = [{
DisplayGroup: 'ABC',
Value: 5
}, {
DisplayGroup: 'DEF',
Value: 3
}, {
DisplayGroup: 'ABC',
Value: 6
}, {
DisplayGroup: 'GHI',
Value: 2
}];
Array.prototype.groupBy = function( key,value){
var newArray = []
var temp = []
this.filter((c,i,a)=> {
var ob = {}
if(temp.indexOf(c[key]) == -1){
ob[c[key]] = c[value] ;
newArray.push(ob)
temp.push(c[key]);
}
else{
newArray.filter((e)=> {
if(e[c[key]]){
e[c[key]] = e[c[key]] + c[value]
}
});
}
})
return newArray;
}
console.log(array.groupBy('DisplayGroup','Value'))
Is there a way to iterate through the array and create a new array to then use?
There's no need to create a new array, you can just use array reduction to create an object that contains all the data. The approach you can take is to iterate through the array and build the object by initializing not yet found values and incrementing the already initialized:
var convertedObject = arr.reduce(function(obj, item) {
var g = item.DisplayGroup;
var v = item.Value;
if (typeof obj[g] !== 'number') {
obj[g] = v; // initialize value that wasn't found yet
} else {
obj[g] += v; // update the value with the current increment
}
return obj;
}, {});
Then you can build the table using a similar loop to the one you have:
$.each(convertedObject, function(key, value) {
table.append('<tr><td>' + key + '</td><td>' + value + '<td></tr>');
});
Here's a running example:
var arr = [{
DisplayGroup: 'ABC',
Value: 5
}, {
DisplayGroup: 'DEF',
Value: 3
}, {
DisplayGroup: 'ABC',
Value: 6
}, {
DisplayGroup: 'GHI',
Value: 2
}];
// reducing into an object
var convertedObject = arr.reduce(function(obj, item) {
var g = item.DisplayGroup;
var v = item.Value;
if (typeof obj[g] !== 'number') {
obj[g] = v; // initialize value that wasn't found yet
} else {
obj[g] += v; // update the value with the current increment
}
return obj;
}, {});
var table = $('#table');
$.each(convertedObject, function(key, value) {
table.append('<tr><td>' + key + '</td><td>' + value + '<td></tr>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="table">
</table>
If you need to, this is how you can convert this object into an array:
var convertedArray = Object.keys(convertedObject).map(function(key) {
var obj = {};
obj[key] = object[key];
return obj;
});

How to group data with similar keys?

I have this data from CSV:
Group Profession Status Count
6 Fisherman Offer Accepted 1
6 Fisherman All 1
7 Fisherman Offer Accepted 1
7 Fisherman All 1
8 Banker Onboard 2
8 Banker All 2
8 Cook Onboard 4
8 Cook All 4
8 Developer Onboard 2
8 Developer All 2
9 Banker Onboard 2
9 Banker Offer Accepted 1
9 Banker All 3
Which I need to return as a JSON array:
"Fisherman" : {
6 : {
"Offer Accepted" : 1,
"All" : 1
},
7 : {
"Offer Accepted" : 1,
"All" : 1
}
},
"Banker" : {
8 : {
"Onboard" : 2,
"All" : 2
},
9 : {
"Onboard" : 2,
"Offer Accepted" : 1,
"All" : 3
}
},
....so on
So far, what I did was I got all the unique Profession and Group.
Then I looped through all the data and compared if there's a match for Profession AND Group.
for(var d in data) {
var json = [];
for(var p in profession) {
for(var g in group) {
if(data[d]["Profession"] == profession[p] && data[d]["Group"] == group[g]) {
json.push({data[d]["Status"] : data[d]["Count"]});
// put 'json' variable in JSON array with key group?
}
}
}
}
If there is a match, I created an array wherein I pushed the Status and Count.
But I really don't know how to proceed from there.
Thank you for your help!
Suppose data is an array with objects like,
{ Group: 6, Profession: 'Fisherman', Status: 'Offer Accepted', Count: 1 }
then you could use the following
var order = ['Profession', 'Group', 'Status'],
object = {};
data.forEach(function (d) {
order.reduce(function (r, a) {
r[d[a]] = r[d[a]] || {};
return r[d[a]];
}, object).Count = d.Count;
});
How it works:
d is an object with the structure like above. oder is an array with keys in the wanted order for the result object. (I renamed json to object, because JSON is a string with a special formatting and not an object, like here necessary.)
For an assignment of count, it is necessary to know the path to the property. This is granted with iterating over the order for the keys of the actual object d.
r[d[a]] = r[d[a]] || {};
This d[a] is taken for a check if the property exits and if not to assign an empty object.
At the end of the callback, the reference to the last object r[d[a]] is returned.
At last, a new property Count is assinged with the value of d.Count
object a d[a] return value
---------------------------- ---------- -------------- ------------
{} Profession Fisherman {}
/--------------------------------------/ (same reference)
{ "Fisherman": {} } Group 6 {}
/-------------------------------/ (same reference)
{ "Fisherman": { "6": {} } } Status Offer Accepted {}
object after first loop of data
{
"Fisherman": {
"6": {
"Offer Accepted": {
"Count": 1
}
}
}
}
Roundup: reduce returns something, which is highly controllable.
Try this:
var result = new Array();
for(var d in data){
if(result[d.profession] == 'undefined'){
result[d.profession] = new Array();
}
if(result[d.profession][d.group] == 'undefined'){
result[d.profession][d.group] = new Array();
}
result[d.profession][d.group][d.status] = d.count;
}
result = JSON.stringify(result);//convert array to json
console.log(result);
I didn't test it and I supposed your JSON data are in data variable
You can do it quite easy with reduce:
const result = data.reduce((result, row) => {
ensureKeyExists(result, row.Profession);
ensureKeyExists(result[row.Profession], row.Group);
result[row.Profession][row.Group][row.Status] = row.Count;
return result;
}, {});
function ensureKeyExists(object, key, defaultVal = {}) {
if (!object[key]) {
object[key] = defaultVal;
}
}
Full example: https://jsfiddle.net/k1zk3ses/
Assuming your data is in this shape, one solution can be produced by using Array.prototype.reduce() as follows;
var str = 'Group,Profession,Status,Count\n6,Fisherman,OfferAccepted,1\n6,Fisherman,All,1\n7,Fisherman,OfferAccepted,1\n7,Fisherman,All,1\n8,Banker,On Board,2\n8,Banker,All,2\n8,Cook,On Board,4\n8,Cook,All,4\n8,Developer,On Board,2\n8,Developer,All,2\n9,Banker,On Board,2\n9,Banker,OfferAccepted,1\n9,Banker,All,3',
data = str.split("\n").map(s => s.split(",")).slice(1),
jdata = data.reduce((p,c) => (p[c[1]] ? p[c[1]][c[0]] ? p[c[1]][c[0]][c[2]] = c[3]
: p[c[1]][c[0]] = {[c[2]]:c[3]}
: p[c[1]] = {[c[0]]:{[c[2]]:c[3]}},p),{});
document.write("<pre>" + JSON.stringify(jdata,null,2) + "</pre>");

How to covert JSON data in separate arrays in javascript?

My JSON data has following format :
[{"Name":"A","Id":"1"},{"Name":"B","Id":"2"},{"Name":"C","Id":"3"}]
How covert this into two separate arrays as Name[] and Id[] using JavaScript ?
I need the data in the following manner:
Name[0] should be : "A"
Name[1] should be : "B" and so on ...
this should work, jsonArray is your JSON
var name = [], ids = [];
jsonArray.forEach(function(item){
name.push(item.Name);
ids.push(item.Id);
}
var data = [{"Name":"A","Id":"1"},{"Name":"B","Id":"2"},{"Name":"C","Id":"3"}];
var result = {};
for (var i=0; i<data.length; i++) {
for (var key in data[i]) {
var item = data[i][key];
if (key in result)
result[key].push(item);
else
result[key] = [item];
}
}
result.Name // ["A","B","C"]
result.Id // ["1","2","3"]
You could use miso project if you are handling a lot of data with different source.
var ds = new Miso.Dataset({
data: [
{ one : 1, two : 4, three : 7 },
{ one : 2, two : 5, three : 8 }
]
}).fetch({
success: function() {
log( this.column('one').data );
}
});
http://misoproject.com/dataset/api.html#misodataset_i_fetch

How to retrieve values from JSON object in javascript [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can i get values from json and display them in javascript
I have a JSON String which will contain SOAP Message content. This is my JSON string:
{
"xml":{
},
"SOAP-ENV:Envelope":{
"#attributes":"....."
},
"SOAP-ENV:Body":{
"#attributes":{
"bill":{
"customerDetil":{
"customerFirstName":{
"#text":"Mahes"
}
}
}
}
}
}
This is what I am doin in javascript:
var jsonText = xmlToJson(xmlhttp.responseXML);
var myjson = JSON.stringify(jsonText);
alert("JSON"+myjson);
function xmlToJson(xml) {
// Create the return object;
var obj = {};
if (xml.nodeType == 1) {
if (xml.attributes.length > 0) {
obj["#attributes"] = {};
for (var j = 0; j < xml.attributes.length; j++) {
var attribute = xml.attributes.item(j);
obj["#attributes"][attribute.nodeName] = attribute.nodeValue;
}
}
} else if (xml.nodeType == 3) {
obj = xml.nodeValue;
}
if (xml.hasChildNodes()) {
for(var i = 0; i < xml.childNodes.length; i++) {
var item = xml.childNodes.item(i);
var nodeName = item.nodeName;
if (typeof(obj[nodeName]) == "undefined") {
obj[nodeName] = xmlToJson(item);
} else {
if (typeof(obj[nodeName].length) == "undefined") {
var old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(xmlToJson(item));
}
}
}
return obj;
};
Please tell me how to retrieve each value from my JSON string in javascript. For example CustomerFirstName.
Thanks,
narayanan
Well, you either have a JSON string or a Javascript object. There is no such thing as a "JSON object" - JSON is a string notation for encoding a Javascript Object.
If you have a JSON string, you need to turn it into a Javascript Object - search SO for numerous examples.
If you have a Javascript object, you can access attributes via the dot notation, or array notation. E.g.
var obj = { 'foo' : 'bar', 'foo2' : { 'foo3' : 'bar2' }};
obj.foo; // 'bar';
obj['foo']; // 'bar';
obj.foo2['foo3']; // 'bar2';
Parse the JSON string first:
var msgs = JSON.parse(json);
Since JSON strings are simply dictionaries/associative arrays, you can just get the values in javascript by doing something like:
var value = msgs["key"];
In your case, it seems like the value is nested inside multiple dictionaries, so perhaps something like:
var customerName = msgs["SOAP-ENV:Body"]["#attributes"]["bill"]["customerDetil"]["customerFirstName"];
Please go through json.org and json guide. This might help you

Javascript accessing name/value pairs

I'm getting JSON name/value pairs that looks like this:
{
"Name":"parentid",
"Value":"blah"
},
{
"Name":"siteid",
"Value":"blah"
},
{
"Name":"sitename",
"Value":"blah"
}
But I would like to access the "name" value as the KEY, and the "value" value as the VALUE. Is there an elegant way to turn that piece of JSON into something like this?
{'parentid', 'blah'},
{'sitename', 'blah'}
Try this:
var items = [
{
"Name":"parentid",
"Value":"blah"
},
{
"Name":"siteid",
"Value":"blah"
},
{
"Name":"sitename",
"Value":"blah"
}
];
var results = new Object();
for (var i = 0; i < items.length; i++)
{
results[items[i].Name] = items[i].Value;
}
This will result in something like:
var results = { parentid: "Blah", siteid: "Blah", sitename: "Blah" };
One way to do it.
var json = [
{
"Name":"parentid",
"Value":"blah"
},
{
"Name":"siteid",
"Value":"blah"
},
{
"Name":"sitename",
"Value":"blah"
}
];
for ( var i = 0, l = json.length, obj; i < l; i++ )
{
obj = json[i];
json[i] = new Object();
json[i][obj.Name] = obj.Value;
}
// console.log() requires Firebug
console.log( json );
function objectflatten (array) {
var out = {}, i;
for(i = 0; i < array.length; i++) {
out[array[i].name] = array[i].value;
}
return out;
}
This is a function that will take an object in the form you presented, and output it as a "normal" object with the name values as keys, and the value values as values.
I'd recommend using the for( ... in ... ) method for this task. It'll grab the key names like you need.
var jsonObj = eval( '([{ "Name":"parentid", "Value":"blah" }])' );
for( var i = 0, assoc = {}, key; i < jsonObj.length; ++i )
{
for( key in jsonObj[ i ] ) // <-- this right here
{
assoc[ key ] = jsonObj[ i ][ key ];
}
}
and you end up with (from Firebug)
Object Name=parentid Value=blah
that can be accessed by object.key or object[ 'key' ] (in our case assoc.Name or assoc[ 'Value' ])
here's a link from Douglas Crockford from Yahoo! about using it as well - http://yuiblog.com/blog/2006/09/26/for-in-intrigue/
I'm assuming you are using PHP, and the PHP echoes you assosiatice aray like this:
echo json_encode($result);
In your javascript, you could do this:
// Soemthing retrieves php result and puts it in `var result`.
data = eval("(" + result+ ")");
alert(data.parentid);
I'm not sure if this is what you want, but it's a solution.

Categories