I have some JSON that looks like this:
{
"ST": "Security",
"C1": "Login failures",
"C2": "1",
"C3": {},
"P1": "2",
"P2": "administrator",
"P3": {},
"P4": {},
"DESCR": "failed login attempts",
"SID": "88",
"AV": "NO",
"SC": "0",
"CN": {}
}
I also have this jQuery loop to filter out values:
$.each(data, function(key, value) {
var innerArr = [];
$.each(value, function(innerKey, innerValue) {
innerArr.push(innerValue);
});
valueArr.push(innerArr);
});
The problem is that on items C3, P3, P4 & CN in my example, the each loop is pushing the value [object Object] into my value collection.
Is there a way to make these items empty strings rather than objects?
You could use:
...
if(typeof innerValue == "object") innerValue = JSON.stringify(innerValue);
valueArr.push(innerValue);
....
The stringify method of the JSON object turns an object into a string. The empty object {} will turn in "{}". If you want to add an empty string instead, use:
if(typeof innerValue == "object"){
innerValue = JSON.stringify(innerValue);
if(innerValue == "{}") innerValue = "";
}
valueArr.push(innerValue);
If you're 100% sure that your object is empty, you don't have to use JSON.stringify. typeof innerValue == "onject" would then be sufficient, to check whether you have to add "" instead of innerValue.
An alternative method to check whether an object is empty or not:
if(typeof innerValue == "object"){
var isEmpty = true;
for(var i in innerValue){
isEmpty = false;
break;
}
if(isEmpty) innerValue = "";
else {
//Object not empty, consider JSON.stringify
}
}
valueArr.push(innerValue);
$.each(data, function(key, value) {
var innerArr = [];
$.each(value, function(innerKey, innerValue) {
if (typeof innerValue == 'object') {
innerValue = '';
}
innerArr.push(innerValue);
});
valueArr.push(innerArr);
});
FYI, you can use .parseJSON function and get results easily
var obj = jQuery.parseJSON('{"ST":"Security"}');
alert( obj.ST === "Security" );
$.each(data, function(key, value) {
var innerArr = [];
$.each(value, function(innerKey, innerValue) {
innerValue = ($.isEmptyObject(innerValue)) ? '' : innerValue;
innerArr.push(innerValue);
});
valueArr.push(innerArr);
});
Edit:
If you didn't want to rely on jQuery's isEmptyObject() function, you could implement one yourself:
Object.size = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
// Get the size of an object
var size = Object.size(myArray);
$.each(data, function(key, value) {
var innerArr = [];
$.each(value, function(innerKey, innerValue) {
innerArr.push(innerValue);
});
//valueArr.push(innerArr);
valueArr.push(innerArr.join());
});
What is the inside loop for? It loops on each single letter of the String values.
$.each(data, function(key, value) {
var innerArr = [];
if (jQuery.isEmptyObject(value)) {
value = '';
}
...
});
Anyway you can use jQuery.isEmptyObject() to test easily if value is an empty object and modify it to an empty string.
Related
If I have a JSON, for example:
{
"test1":{
"test11":"someting",
"test12":"something else"
},
"test2":{
"test21":"asdasd",
"test22":"qwasd"
}
}
I want to access and modify some data but i don't know which one.
I'll have an array of keys like this:
["test2","test22"] and a value: "change to this".
I want to change the myjson.test2.test22 data to "change to this".
Is there some simple and elegant way to do this?
Note that I don't know what the array's content will be, so I cant use the myjson.test2.test22 access method.
Try this
function setDeep(obj, props, value) {
var cur = obj,
prop;
while ((prop = props.shift()) && props.length) {
cur = cur[prop]
}
cur[prop] = value
return obj;
}
var obj = {
"test1": {
"test11": "someting",
"test12": "something else"
},
"test2": {
"test21": "asdasd",
"test22": "qwasd"
}
}
setDeep(obj, ['test1', 'test12'], 'new value');
console.log(obj)
You could use Array#reduce and walk the path. Then assign the value to the object with the last key.
var object = { "test1": { "test11": "someting", "test12": "something else" }, "test2": { "test21": "asdasd", "test22": "qwasd" } },
path = ["test2", "test22"],
lastKey = path.pop();
path.reduce(function (o, k) {
return o[k];
}, object)[lastKey] = 'change to this';
console.log(object);
For unknow properties, i suggets to make a check befor and use a default object then.
var object = { "test1": { "test11": "someting", "test12": "something else" }, "test2": { "test21": "asdasd", "test22": "qwasd" } },
path = ["test2", "test22", "42"],
lastKey = path.pop();
path.reduce(function (o, k) {
(o[k] !== null && typeof o[k] === 'object') || (o[k] = {});
return o[k];
}, object)[lastKey] = 'change to this';
console.log(object);
Following is a recursive function the traverses the keys of an object until the matching key (last one in the array) is found then it's value is changed and the changed object is returned. base case is when the array of keys is empty. Returns false if the key is not found
given an object named obj
var obj = {
"test1":{
"test11":"someting",
"test12":"something else"
},
"test2":{
"test21":"asdasd",
"test22":"qwasd"
}
function changeAkey(object, arrayOfKeys, value){
if(arrayOfKeys.length == 0)
return value;
else{
if(!object[arrayOfKeys[0]])
return false;
else
object[arrayOfKeys[0]] = changeAkey(object[arrayOfKeys[0]], arrayOfKeys.slice(1), value);
return object;
}
}
so changeAkey(obj, ["test2", "test22"], value) would do the job
I would start by checking if the property exists and if it does change the data. This way it won't throw an unspecific error.
var keys = ["key1", "key2"];
var myObj = {
"random1": {
"random2": "someting",
"random3": "something else"
},
"key1": {
"random4": "asdasd",
"key2": "qwasd"
};
}
var hasKeys = myObj[keys[0]][keys[1]] || null;
if(hasKeys) {
myObj[keys[0]][keys[1]] = "some data";
} else {
console.log('property not found');
}
I would propose to serialize your object and use String replace(). It works for any depth and simple code.
var objStr = JSON.stringify(obj);
changes.forEach(function(item){
objStr = objStr.replace(item, to);
})
obj = JSON.parse(objStr);
var obj = {
"test1":{
"test11":"someting",
"test12":"something else"
},
"test2":{
"test21":"asdasd",
"test22":"qwasd"
}
}
var changes = ["test11", "test21"];
var to = 'change to this';
var objStr = JSON.stringify(obj);
changes.forEach(function(item){
objStr = objStr.replace(item, to);
})
obj = JSON.parse(objStr);
console.log(obj)
var obj = {
"test1":{
"test11":"someting",
"test12":"something else"
},
"test2":{
"test21":"asdasd",
"test22":"qwasd"
}
};
var keys = ["test2","test22"];
function update_obj(obj, keys, value) {
for (var i = 0; i < keys.length - 1; i++) {
obj = obj[keys[i]];
}
obj[keys[keys.length - 1]] = value;
}
update_obj(obj, keys, "hi");
console.log(obj);
i have nested json data. i used the blow function.
var jsonSource={"error_code":0, "ext_info":{"name":{"firstName":"John","lastName":"Jonson","nickName":"JJ"}}};
var obj=JSON.parse(jsonSource),returnValue;
function showJson(obj){
for(var key in obj){
if(typeof obj[key]==='object'){
returnValue+='<div>'+key+'/\n';
showJson(obj[key]);
returnValue+='</div>';
} else{
returnValue+=key+'equal'+obj[key];
}
}
docoument.getElementById('data').innerHTML=returnValue;
}
as i said before , i have a large nested json data and when i parse it to showJson function ,it just shows one level of json data and puts others deep level of dataJson undefined.
what should i do to resolve the problem?
Recursive approach works more intuitively when done with actual return values. Have a look at https://jsfiddle.net/ughnjfh0/1/
var jsonSource='{"error_code":0, "ext_info":{"name":{"firstName":"John","lastName":"Jonson","nickName":"JJ"}}}';
var obj=JSON.parse(jsonSource);
function showJson(obj){
var returnValue='';
for(var key in obj){
if(typeof obj[key]==='object'){
returnValue+='<div>'+key+'/\n';
returnValue+=showJson(obj[key]);
returnValue+='</div>';
} else{
returnValue+=key+'equal'+obj[key];
}
}
return returnValue;
}
document.getElementById('data').innerHTML= showJson(obj);
Also:
jsonSource should be a string to be properly parsable as JSON data
typo in docoument.getElementById('data').innerHTML=returnValue;
Some of your problems:
jsonSource is already an object
you try to assign the returnValue in every call of showJson
Better to use a clean approach for looping and returning of the items:
var obj = { "error_code": 0, "ext_info": { "name": { "firstName": "John", "lastName": "Jonson", "nickName": "JJ" } } };
function showObj(obj) {
return Object.keys(obj).map(function (k) {
if (typeof obj[k] === 'object') {
return k + ':<br><div style="margin-left: 25px;">' + showObj(obj[k]) + '</div>';
}
return k + ': ' + obj[k];
}).join('<br>');
}
document.getElementById('data').innerHTML = showObj(obj);
<div id="data"></div>
// obj is the object to loop, ul is the ul to append lis to
function loop(obj, ul) {
$.each(obj, function(key, val) {
if(val && typeof val === "object") { // object, call recursively
var ul2 = $("<ul>").appendTo(
$("<li>").appendTo(ul)
);
loop(val, ul2);
} else {
$("<li>").text(val).appendTo(ul);
}
});
}
var ul = $("<ul>");
var jsonSource={"error_code":0, "ext_info":{"name":{"firstName":"John","lastName":"Jonson","nickName":"JJ"}}};
var data=JSON.parse(jsonSource)
loop(data, ul);
ul.addClass("my-new-list").appendTo('body');
I have the following json output from an ajax call ,
{17: {access: "1",id: "2"}}
I'd like to iterate and get value of id , I am using below code but I get error of undefined in console .
$(obj).each(function(i, val) {
console.log(val.id);
});
What am I doing wrong ?
You can do it like this:
var obj = {17: {access: "1",id: "2"}}
// Native JS
for (var k in obj) {
console.log(obj[k].id)
}
// JQuery
// Documentaion: http://api.jquery.com/jquery.each/
$.each(obj, function(i, val) {
console.log(val.id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Hope it helps, any questions?
As requested I'd like to point out that the term "JSON-Object" doesn't realy exist. You are using a simple JavaScript-Object, wich can be made of an JSON-String 😇
In this case you should use $.each from jQuery utils
var obj = {17: {access: "1",id: "2"}}
$.each(obj, function(i, val) {
console.log(val.id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You have to use $.each(array, callback):
var obj = {
17: { id: "2", access: "1" },
23: { id: "8" }
};
$.each(obj, function(i, val) {
console.log(val.id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
Try the below code.
var obj = {17: {access: "1",id: "2"}};
if( $.isPlainObject(obj) ) {
$(obj).each(function(i, val) {
console.log(val.id);
});
}
else {
console.log('invalid Object');
}
A solution with Object.keys() and Array.prototype.some() in a recursion style.
var object = { 17: { access: "1", id: "2" } };
function find(p, o) {
var result;
Object.keys(o).some(function (k) {
if (k === p) {
result = o[k];
return true;
}
if (typeof o[k] === 'object') {
result = find(p, o[k]);
}
});
return result;
}
document.write('<pre>' + JSON.stringify(find('id', object), 0, 4) + '</pre>');
You are making an jQuery object of your JSON and then iterating over that jQuery object. Take a look at the API docs of jQuery.each():
You are supposed to use it like this:
jQuery.each(object, callback)
Where object is the object to iterate over and callback is the callback function to be run for every key in object.
var obj = {
17: {
access: "1",
id: "2"
},
18: {
access: "2",
id: "5"
}
};
$.each(obj, function(i, val) {
document.body.innerHTML += val.id + "<br>";
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I am attempting to abuse a reviver function with JSON.parse.
I basically want to make certain fields "null".
If I do this:
var json_data = JSON.parse(j, function(key, value) {
if (key == "name") {
return value;
} else {
return null;
}
});
The entire json_data object ends up null. In fact, no matter what I make the else, that defines the value of the json_object.
Interestingly, this works as expected:
var json_data = JSON.parse(j, function(key, value) {
if (key == "name") {
return "name";
} else {
return value;
}
});
The property "name" now has a value of "name".
JSON in question:
var j = '{"uuid":"62cfb2ec-9e43-11e1-abf2-70cd60fffe0e","count":1,"name":"Marvin","date":"2012-05-13T14:06:45+10:00"}';
Update
I just realized that the inverse of what I want to do works as well so I can nullify the name field:
var json_data = JSON.parse(j, function(key, value) {
if (key == "name") {
return null;
} else {
return value;
}
});
Through some experimentation, it looks like a final call is made to the function where the key is an empty string and the value is the top-level object:
> JSON.parse('{"hello": "world"}', function(k, v) { console.log(arguments); return v; })
["hello", "world"]
["", Object]
So you could use:
var json_data = JSON.parse(j, function(key, value) {
if (key == "name" || key === "") {
return value;
} else {
return null;
}
});
Now, since "" does appear to be a valid JSON key, to be 100% correct it might be better to use something like:
var json_data;
JSON.parse(j, function(key, value) {
if (key == "name") {
return value;
} else if (key === "") {
json_data = value;
return null;
} else {
return null;
}
});
But that might be a little bit paranoid ;)
It has a rather interesting behavior that the entire object is included in the objects passed to the reviver.
When the entire object is passed, the key is null.
http://jsfiddle.net/sGYGM/7/
var j = '{"uuid":"62cfb2ec-9e43-11e1-abf2-70cd60fffe0e","count":1,"name":"Marvin","date":"2012-05-13T14:06:45+10:00"}';
var json_data = JSON.parse(j, function(k, v) {
if (k === "" || k == "name") {
return v;
} else {
return null;
}
});
console.log(json_data);
As per https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/parse
The reviver is ultimately called with the empty string and the topmost value to permit transformation of the topmost value. Be certain to handle this case properly, usually by returning the provided value, or JSON.parse will return undefined.
I have some JSON-code which has multiple objects in it:
[
{
"MNGR_NAME": "Mark",
"MGR_ID": "M44",
"EMP_ID": "1849"
},
{
"MNGR_NAME": "Steve",
"PROJ_ID": "88421",
"PROJ_NAME": "ABC",
"PROJ_ALLOC_NO": "49"
}
]
My JSON loop snippet is:
function ServiceSucceeded(result)
{
for(var x=0; x<result.length; x++)
{
}
}
Could you please let me know how to check there is no occurence of "MNGR_NAME" in the array. (It appears twice in my case.)
You need to access the result object on iteration.
for (var key in result)
{
if (result.hasOwnProperty(key))
{
// here you have access to
var MNGR_NAME = result[key].MNGR_NAME;
var MGR_ID = result[key].MGR_ID;
}
}
You could use jQuery's $.each:
var exists = false;
$.each(arr, function(index, obj){
if(typeof(obj.MNGR_NAME) !== 'undefined'){
exists = true;
return false;
}
});
alert('Does a manager exists? ' + exists);
Returning false will break the each, so when one manager is encountered, the iteration will stop.
Note that your object is an array of JavaScript objects.
Could you use something like this?
var array = [{
"MNGR_NAME": "Mark",
"MGR_ID": "M44",
"EMP_ID": "1849"
},
{
"MNGR_NAME": "Steve",
"PROJ_ID": "88421",
"PROJ_NAME": "ABC",
"PROJ_ALLOC_NO": "49"
}];
var numberOfMngrName = 0;
for(var i=0;i<array.length;i++){
if(array[i].MNGR_NAME != null){
numberOfMngrName++;
}
}
console.log(numberOfMngrName);
This will find the number of occurrences of the MNGR_NAME key in your Object Array:
var numMngrName = 0;
$.each(json, function () {
// 'this' is the Object you are iterating over
if (this.MNGR_NAME !== undefined) {
numMngrName++;
}
});
Within the loop result[x] is the object, so if you wanted to count a member that may or may not be present;
function ServiceSucceeded(result)
{
var managers = 0
for(var x=0; x<result.length; x++)
{
if (typeof result[x].MNGR_NAME !== "undefined")
managers++;
}
alert(managers);
}
You can iterate over the collection and check each object if it contains the property:
var count = 0;
var i;
for(i = 0; i < jsonObj.length; i += 1) {
if(jsonObj[i]["MNGR_NAME"]) {
count++;
}
}
Working example: http://jsfiddle.net/j3fbQ/
You could use $.each or $.grep, if you also want to get the elements that contain the attribute.
filtered = $.grep(result, function(value) {
return (value["MNGR_NAME"] !== undefined)
});
count = filtered.length
Use ES6...
myobj1.map(items =>
{
if(items.MNGR_NAME) {
return items.MNGR_NAME;
}else {
//do want you want.
}
})
Thanks.