How to access JSON string containing null value in Javascript - javascript

I have this JSON I retrieve from an API that contains null values. How do I better traverse the JSON and abstract the functionality?
const colletionjson =
{ "collections":
[ { "title" : "Home page"
, "description" : null
, "image" : null
}
, { "title" : "Products"
, "description" : "Products"
, "image" : { "src": "https:www.example.com" }
, "products_count" : 3
}
]
}
$.each(collectionjson, function (key, value) {
$.each(value, function (key, value) {
var collectionTitle = value.title;
var collectionDescription = value.description;
if (value == "image" && $.isArray(value)) {
var collectionImage = value.image.src;
} else {
var collectionImage = "";
}
});
});
// Do something with the data

you can now use Optional chaining (?.) with ECMAScript 2020
sample code
const colletionjson = // just a name
{ collections:
[ { title : 'Home page'
, description : null
, image : null
}
, { title : 'Products'
, description : 'Products'
, image : { src : 'https:www.example.com' }
, products_count : 3
}
]
}
colletionjson.collections.forEach((collection, i) =>
{
let collectionTitle = collection.title
, collectionDescription = collection.description || ''
, collectionImage = collection.image?.src || ''
;
console.log (`index: ${i}, title: ${collectionTitle}, description: ${collectionDescription}, image: ${collectionImage}` )
})

if (colletionjson.collections && Array.isArray(colletionjson.collections)) {
colletionjson.collections.forEach(value => {
const collectionTitle = value.title;
const collectionDescription = value.description;
let collectionImage = '';
if (value.image && value.image.src) {
collectionImage = value.image.src;
// do something with this value
}
})
}

Related

'filter' filter in AngularJS

I have an array of objects and I want to extract the value when key is passes in 'filter' filter. Below is the controller code snippet I have tried, but the type of response I get is undefined. Please help me in finding where am I going wrong.
var states = [{"HIMACHAL PRADESH":"HP"},{"JAMMU AND KASHMIR":"JK"},{"JHARKHAND":"JH"},{"KARNATAKA":"KA"},{"KERALA":"KL"},{"MADHYA PRADESH":"MP"},{"MAHARASHTRA":"MH"},{"ORISSA":"OR"}]
var str = "ORISSA";
var abbr = $filter('filter')(states, {key: str}, true).value;
console.log ("ABBR:"+abbr);
P.S. I have injected $filter in the controller
Use Object.keys and find
var matchedState = states.find( s => Object.keys( s )[0] == str );
var abbr = matchedState ? matchedState[str] : ""
Demo
var states = [{
"HIMACHAL PRADESH": "HP"
}, {
"JAMMU AND KASHMIR": "JK"
}, {
"JHARKHAND": "JH"
}, {
"KARNATAKA": "KA"
}, {
"KERALA": "KL"
}, {
"MADHYA PRADESH": "MP"
}, {
"MAHARASHTRA": "MH"
}, {
"ORISSA": "OR"
}]
var str = "ORISSA";
var matchedState = states.find(s => Object.keys(s)[0] == str);
var abbr = matchedState ? matchedState[str] : ""
console.log(abbr);

Cloud Functions for Firebase - Remove oldest child

I have a onWrite cloud function set up to listen for when a user updates something. I'm trying to delete the oldest child if there are more than 3, this is there I'm at:
exports.removeOld = functions.database.ref('/users/{uid}/media').onWrite(event => {
const uid = event.params.uid
if(event.data.numChildren() > 3) {
//Remove Oldest child...
}
})
Each of these children has a "timestamp" key.
{
"users" : {
"jKAWX7v9dSOsJtatyHHXPQ3MO193" : {
"media" : {
"-Kq2_NvqCXCg_ogVRvA" : {
"date" : 1.501151203274347E9,
"title" : "Something..."
},
"-Kq2_V3t_kws3vlAt6B" : {
"date" : 1.501151232526373E9,
"title" : "Hello World.."
}
"-Kq2_V3t_kws3B6B" : {
"date" : 1.501151232526373E9,
"title" : "Hello World.."
}
}
}
}
}
So in the above example, when the text value is added to "media", the oldest would be delete.
This sample should help you.
You need something like that :
const MAX_LOG_COUNT = 3;
exports.removeOld = functions.database.ref('/users/{uid}/media/{mediaId}').onCreate(event => {
const parentRef = event.data.ref.parent;
return parentRef.once('value').then(snapshot => {
if (snapshot.numChildren() >= MAX_LOG_COUNT) {
let childCount = 0;
const updates = {};
snapshot.forEach(function(child) {
if (++childCount <= snapshot.numChildren() - MAX_LOG_COUNT) {
updates[child.key] = null;
}
});
// Update the parent. This effectively removes the extra children.
return parentRef.update(updates);
}
});
});
You can find all Cloud Functions for Firebase samples here.

How to check if a dynamic collection of objects have the same keys recursively?

I am given an object which has dynamic properties, but all of its properties values are objects too (keys at this level can differ which is fine). But for each of these objects, I want to make sure all of them have the same keys and recursively too. For example
Given A where
A = {
'en' : {
's1' : '',
's2' : {
's3' : '',
's4' : ''
}
},
'fr' : {
's1' : '',
's2' : {
's3' : '',
's4' : ''
}
}
}
these two are the same, because they have the same key values recursively.
A = {
'en' : {
's1' : '',
's2' : {
's3' : '',
's4' : ''
}
},
'fr' : {
's1' : '',
's2' : {
's3' : '',
's5' : ''
}
}
}
this would be false because s5 is different and don't exist in at least one other.
Essentially the purpose is to create an object which has language objects inside and I can put any language objects I want, so its dynamic. But for each language object, all it's keys should be synchronized and the same with all other language object.
I have this
this.compareKeys = function(dataObj) {
var checkObj = {};
for(var prop in dataObj) {
if (dataObj.hasOwnProperty(prop)) {
var obj = dataObj[prop];
var keysStr = JSON.stringify(Object.keys(obj).sort());
var keys = Object.keys(checkObj);
if (keys.length == 0) {
checkObj[keysStr] = true;
} else if (!checkObj.hasOwnProperty(keysStr)) {
return false;
}
}
}
return true;
}
but how do I make it work for recursively? This only checks 1 level deep.
Thanks
You can compare the lang object with a structure object:
var struct = {
's1' : '',
's2' : {
's3' : '',
's4' : ''
}
}
var lang = {
'en' : {
's1' : '',
's2' : {
's3' : '',
's4' : ''
}
},
'fr' : {
's1' : '',
's2' : {
's3' : '',
's4' : ''
}
}
}
Therefore get all keys in the lang object recursively:
function getAllKeys(obj, res) { // Get all keys in string format
for(k in obj) {
res.push(k);
if(typeof(obj[k]) === "object") {
var o = obj[k];
getAllKeys(o, res);
}
}
return res.join("");
}
You give this function an object and a result array as arguements:
function f(obj, []) { ... }
Check if the value is an object:
if(typeof(obj[k]) === "object") { ... }
If so run the function again with obj[k] as the new object and so on.
For comparison reasons the function outputs a string!
The next step is to compare lang object with structure object:
function compareObjWithStructure(obj, struct) {
var s = getAllKeys(struct, []);
for(k in obj) {
var ks = getAllKeys(obj[k], []);
if(ks !== s) {
return false;
} else {
return true;
}
}
}
JSFiddle
You can compare two objects level by level with passing keys array.
if (obj1.constructor === Array && obj2.constructor === Array) {
flag = obj1.length === obj2.length;
if (flag) {
obj1.forEach(function(key) {
map[key] = (map[key] || 0) + 1;
});
obj2.forEach(function(key) {
flag = flag && (map[key] !== undefined);
});
}
return flag;
}
If this level keys are the same, then check their children.
Object.keys(obj1).forEach(function(key) {
if (typeof obj1[key] === 'object') {
flag = flag && compareKeys(obj1[key], obj2[key]);
}
});
Here is the jsfiddle link
Hope this is useful.

Using chrome bookmarks getTree function with callback for data source with jsTree

I'm creating a chrome extension that populates a jstree with the user's Chrome bookmarks. I am obtaining and modifying the json data returned via chrome.bookmarks.getTree with the following code. I need to figure out how to obtain and modify the data all by passing a function into the tree initiation. JsTree docs say you can pass a function in as data here. I'm thinking it may not be possible though because of the callback... I'm not sure. Does anyone know how to do this?
My current code... need to change it to include getting and modifying all the data in the tree initialization:
function initBookmarks(){
chrome.bookmarks.getTree(parseBookmarks);
}
function modifyData(o){
var string = JSON.stringify(o);
string = string.replace(/\"title\":/g, "\"text\":");
string = string.replace(/\"url\":/g, "\"type\": \"url\", \"url\":");
var obj = JSON.parse(string);
console.log('new obj is ', obj);
return obj;
}
function parseBookmarks(data){
console.log('the bookmarks are ' , data);
data = modifyData(data[0].children);
$('#bookmarks').jstree({
'core' : {
//expand_selected_onload : true,
'data' : data,
'check_callback' : function(o, n, p, i, m) { //operation, node, node_parent, node_position, more
//console.log(o,n,p,i,m);
if(m && m.dnd && m.pos !== 'i') { return false; }
if(o === "move_node" || o === "copy_node") {
if(this.get_node(n).parent === this.get_node(p).id) { return false; } //if current nodes parent matches parent nodes id, dont do anything
}
return true;
},
'themes' : {
'responsive' : false,
'variant' : 'small',
'stripes' : true
}
},
"search": {
"case_insensitive": true,
"show_only_matches" : true
},
//loaded : runTourStep,
'sort' : function(a, b) {
return this.get_type(a) === this.get_type(b) ? (this.get_text(a) > this.get_text(b) ? 1 : -1) : (this.get_type(a) >= this.get_type(b) ? 1 : -1);
},
'contextmenu' : {
'items' : bookmarksContextMenu,
'select_node' : false
},
'types' : {
'default' : { 'icon' : 'images/folder-horizontal.png' },
'url' : { 'valid_children' : [], 'icon' : 'images/globe_icon.gif' }
},
'unique' : {
'duplicate' : function (name, counter) {
return name + ' ' + counter;
}
},
'plugins' : ['dnd','types','contextmenu','unique', 'search', 'wholerow'] //took out 'state' plugin
})
bookmarkMethods();
}
initBookmarks on DOM ready...
So I've tried the following but it does not work!
function modifyData(o){
//that's all... no magic, no bloated framework
/*traverse(o,function(key,value){
});*/
o = o[0].children;
var string = JSON.stringify(o);
string = string.replace(/\"title\":/g, "\"text\":");
string = string.replace(/\"url\":/g, "\"type\": \"url\", \"url\":");
var obj = JSON.parse(string);
console.log('new obj is ', obj);
return obj;
}
function parseBookmarks(){
//console.log('the bookmarks are ' , data);
//data = modifyData(data[0].children);
$('#bookmarks').jstree({
'core' : {
//expand_selected_onload : true,
'data' : chrome.bookmarks.getTree(modifyData),
'check_callback' : function(o, n, p, i, m) { //operation, node, node_parent, node_position, more
//console.log(o,n,p,i,m);
//if(m && m.dnd && m.pos !== 'i') { return false; }
if(o === "move_node" || o === "copy_node") {
//if(this.get_node(n).parent === this.get_node(p).id) { return false; } //if current nodes parent matches parent nodes id, dont do anything
}
return true;
},
'themes' : {
'responsive' : false,
'variant' : 'small',
'stripes' : true
}
},
"search": {
"case_insensitive": true,
"show_only_matches" : true
},
//loaded : runTourStep,
'sort' : function(a, b) {
return this.get_type(a) === this.get_type(b) ? (this.get_text(a) > this.get_text(b) ? 1 : -1) : (this.get_type(a) >= this.get_type(b) ? 1 : -1);
},
'contextmenu' : {
'items' : bookmarksContextMenu,
'select_node' : false
},
'types' : {
'default' : { 'icon' : 'images/folder-horizontal.png' },
'url' : { 'valid_children' : [], 'icon' : 'images/globe_icon.gif' }
},
'unique' : {
'duplicate' : function (name, counter) {
return name + ' ' + counter;
}
},
'plugins' : ['dnd','types','contextmenu','unique', 'search', 'wholerow'] //took out 'state' plugin
})
bookmarkMethods();
}
parseBookmarks() on DOM ready..

mongodb updating only specific subelements

my db structure looks like:
{
"_id" : ObjectId("51e66873f6a6600436000001")
,"email" : "asd#asd.de",
,"attribute_group_a" : {
"attribute_a" : ""
,"attribute_b" : ""
,"attribute_c" : ""
,"attribute_d" : ""
},
,"attribute_group_b" : {
"attribute_subgroup_b_a" : {
"attribute_a" : ""
,"attribute_b" : ""
,"attribute_c" : ""
,"attribute_d" : ""
}
,"attribute_subgroup_b_b" : {
"attribute_a" : ""
,"attribute_b" : ""
,"attribute_c" : ""
,"attribute_d" : ""
}
}
}
so lets say i want to update att_subgrp_b_a:
exports.updateProfil = function(req, res, item, callback) {
var email = req.session.email;
db.collection('profiles', function(err, collection) {
collection.update({"email": email},{$set: item}, function(err, result)
the var "item" looks like:
{
attribute_group_b:
{
attribute_subgroupgroup_b_a:
{
att_a: "xy"
,att_b: "xy"
}
}
}
when i now update the file => it deletes everything in attr_group_b and replaces it with "item"
that means attr_subgrp_b_b is totally gone and all other attributes (of attr_subgrp_b_a) that weren't updated
i want that it looks for the attributes in "item", replaces them into db letting all other obj untouched
Try the query below
var email='emailid';
var item='whichuwanttoupdate';
collection.update(
{"email": email},
{$set:{'attribute_group_b.attribute_subgroup_b_a':item}},
function(err,result){
});

Categories