how to get data from dynamic key pair value in Angular - javascript

here my issue i unable to get the dynamic key pair value from the dynamic json
below is my json
var d = {
"pexels-photo.jpeg": {
"information": "laptop",
"desc": {
"mimetype": "image/jpeg",
"id": "shsj44",
"file_id": "pexels-photo.jpeg"
},
"_id": "shsj44"
}
}
here i tried below
Object.keys(d).forEach(function(key){
var value = d[key];
console.log(key + ':' + value) ;
});
i want to get the id value "_id" & "file_id" values

You can use Destructuring assignment
var d = {"dynamic": {"information": "laptop","desc": { "mimetype": "image/jpeg","id": "shsj44","file_id": "pexels-photo.jpeg" },"_id": "shsj44"}}
let dynamicKey = Object.keys(d)[0]
let {[dynamicKey]:{desc:{
file_id
},_id}} = d
console.log(file_id, '\n', _id)

That is because of the + before the value, which will try to concatenate the value and you will see [object object]
var d = {
"pexels-photo.jpeg": {
"information": "laptop",
"desc": {
"mimetype": "image/jpeg",
"id": "shsj44",
"file_id": "pexels-photo.jpeg"
},
"_id": "shsj44"
}
}
Object.keys(d).forEach(function(key) {
let value = d[key];
console.log(key + ' : ', value);
console.log(key + ' : ', value.desc.id);
});

You need to check whether the value is object or not, if yes then you need to loop over it again.
Following code will print every key-value pair in d
export class AppComponent implements OnInit {
d = {
'pexels-photo.jpeg': {
'information': 'laptop',
'desc': {
'mimetype': 'image/jpeg',
'id': 'shsj44',
'file_id': 'pexels-photo.jpeg'
},
'_id': 'shsj44'
}
};
ngOnInit(): void {
this.calc(this.d);
}
calc(val) {
Object.keys(val).forEach(key => {
const value = val[key];
if (typeof (value) === 'object') {
this.calc(value);
} else {
console.log(key + ':' + value);
}
});
}
}

Try this :
var d = {
"pexels-photo.jpeg": {
"information": "laptop",
"desc": {
"mimetype": "image/jpeg",
"id": "shsj44",
"file_id": "pexels-photo.jpeg"
},
"_id": "shsj44"
}
};
Object.keys(d).filter(key => {
Object.keys(d[key]).filter(item => {
if (item === 'desc') {
Object.keys(d[key][item]).filter(elem => {
if ((elem === 'id') || (elem === 'file_id')) {
console.log(elem + ' : ' + d[key][item][elem]);
}
});
}
})
});

Related

How to convert JSON to list of key with dotnotation

I am converting JSON keys to the list with dot-notation. If any dot is there represent nested jsonobject and if any [](array notation) is there resents jsonarray.
var keyify = (obj, prefix = '') =>
Object.keys(obj).reduce((res, el) => {
if (Array.isArray(obj[el])) {
return [...res, ...keyify(obj[el][0], prefix + el + '[].')];
} else if (typeof obj[el] === 'object' && obj[el] !== null) {
return [...res, ...keyify(obj[el], prefix + el + '.')];
} else {
return [...res, prefix + el];
}
}, []);
Above is the sample code that I am using for the converion. If input is
{
"input": {
"test": {
"phone": [
{
"phone1": "123"
}
]
}
},
"customer": [
{
"lastname": "def",
"firstname": "abc"
}
]
}
Output will be:
[ 'input.test.phone[].phone1',
'customer[].lastname',
'customer[].firstname' ]
But the above code searches for only first JSONObject's keys in the JSONArray. But if the input is like this:
{
"input": {
"test": {
"phone": [
{
"phone1": "123"
},
{
"a": "456"
}
]
}
},
"customer": [
{
"lastname": "def",
"firstname": "abc"
}
]
}
Then in the above JSON case the code will give output :
[ 'input.test.phone[].phone1',
'customer[].lastname',
'customer[].firstname' ]
So, the key a is missing only phone1 is coming in the list.So, how to get if multiple json keys are there then get keys with index of first occurence.
Expected output
[ 'input.test.phone[0].phone1',
'input.test.phone[1].a',
'customer[0].lastname',
'customer[0].firstname' ]
And if the JSONarray is value then it should be replaced by empty string.
For input:
const data = {
"input": {
"test": {
"phone": [
{
"phone1": ["123456"]
},
{
"a": ["1","2","3","4"]
}
]
}
},
"customer": [
{
"lastname": "def",
"firstname": "abc"
}
]
}
In this case "phone1": ["123456"] and "a": ["1","2","3","4"] are Json array as values this case lis will be like:
Expected Output:
[ 'input.test.phone[0].phone1',//instead of 'input.test.phone[0].phone1[0]'
'input.test.phone[1].a',//instead of 'input.test.phone[1].a[0]','input.test.phone[1].a[1]','input.test.phone[1].a[2]','input.test.phone[1].a[3]',
'customer[0].lastname',
'customer[0].firstname' ]
In the above case jsonarray should be considered as value not key.
You could use for...in loop to create recursive function for this and check if the current data input is an array or not to add dot or square brackets.
const data = { "input": { "test": { "phone": [ { "phone1": ["123456"] }, { "a": ["1","2","3","4"] } ] } }, "customer": [ { "lastname": "def", "firstname": "abc" } ] }
function parse(data, prev = '') {
const result = []
const check = data => {
if (typeof data !== 'object') {
return false
}
if (Array.isArray(data)) {
if (data.some(e => (typeof e != 'object'))) {
return false
}
}
return true;
}
for (let i in data) {
let dot = prev ? '.' : ''
let str = Array.isArray(data) ? `[${i}]` : dot + i
let key = prev + str;
if (check(data[i])) {
result.push(...parse(data[i], key))
} else {
result.push(key)
}
}
return result
}
const result = parse(data);
console.log(result)
You can traverse through the scope of the object and capture any paths that have a non-object value.
This is an extremely uncoupled and generic soulution.
const traverse = (obj, visitorFn, scope = []) => {
for (let key in obj) {
visitorFn.apply(this, [key, obj[key], scope]);
if (obj[key] !== null && typeof obj[key] === 'object') {
traverse(obj[key], visitorFn, scope.concat(key));
}
}
}
const scopeToPath = (obj) => obj.reduce((path, key) =>
path + (!isNaN(key) ? `[${key}]` : `.${key}`), '').substring(1);
const findObjectPaths = (obj) => {
let paths = [];
traverse(obj, (key, value, scope) => {
if (typeof value !== 'object') {
paths.push(scopeToPath(scope.concat(key)));
}
});
return paths;
};
console.log(findObjectPaths(getData()));
function getData() {
return {
"input": {
"test": {
"phone": [{ "phone1": "123" }, { "a": "456" }]
}
},
"customer": [{ "lastname": "def", "firstname": "abc" }]
};
}
.as-console-wrapper { top: 0; max-height: 100% !important; }
You could take a nested approach by having a look to the types of the object.
function flat(object, keys = '') {
if (!object || typeof object !== 'object') return [keys];
if (Array.isArray(object))
return object.every(o => !o|| typeof o!== 'object')
? [keys]
: object.flatMap((o, i, { length }) =>
flat(o, `${keys}[${length === 1 ? '' : i}]`));
return Object
.entries(object)
.flatMap(([k, v]) => flat(v, `${keys}${keys && '.'}${k}`));
}
var data = { input: { test: { phone: [{ phone1: ["123456"] }, { a: ["1", "2", "3", "4"] }] } }, customer: [{ lastname: "def", firstname: "abc" }] },
result = flat(data);
console.log(result);

How to generate minimum-size Javascript object?

How can I create a minimum-sized Javascript serialization of a Javascript object? Essentially a JSON.stringify with all unnecessary quotes removed. (Only basic JSON data types need to be supported, not Dates etc.)
For example, the JSON:
{
"pi": 3.14,
"e!": 4.26
}
would become:
{pi:3.14,"e!":4.26}
Edit: The result is not valid JSON, but is valid Javascript.
Copied from https://stackoverflow.com/a/11233515/916000 and modified:
function stringify(obj_from_json) {
if (typeof obj_from_json !== "object") {
return JSON.stringify(obj_from_json);
} else {
if (Array.isArray(obj_from_json)) {
// if the array contains an object
var arr = [];
for (var i = 0, len = obj_from_json.length; i < len; i++) {
arr.push(stringify(obj_from_json[i]));
}
return "[" + arr.join(",") + "]";
} else {
var props = Object
.keys(obj_from_json)
.map(function(key) {
return (new RegExp(/^[1-9a-zA-Z_$][a-zA-Z0-9_$.]*$/).test(key) ? key : "\"" + key + "\"") + ":" + stringify(obj_from_json[key]);
}).join(",");
return "{" + props + "}";
}
}
}
console.log(stringify({
"pi": 3.14,
"e!": 4.26
}));
console.log(stringify([{
"adjacencies": [{
"nodeTo": "graphnode2",
"nodeFrom": "graphnode1",
"data": {
"$color": "#557EAA"
}
}],
"data": {
"$color": "#EBB056",
"$type": "triangle",
"$dim": 9
},
"id": "graphnode1",
"name": "graphnode1"
}, {
"adjacencies": [],
"data": {
"$color": "#EBB056",
"$type": "triangle",
"$dim": 9
},
"id": "graphnode2",
"name": "graphnode2"
}]));
console.log(stringify({1: 2}));
console.log(stringify({"000": 42}));
console.log(stringify({1.26: 42}));
Edit: Added object array support.
Edit: Fixed array conversion.

I have json formated time slots and want to convert in proper time slots as written description

I have below JSON output from nodejs which is listed as below:
`{
"data": {
"2018-08-21": [
{ "available_slots": [
{ "slots": "1.15" },
{ "slots": "2:45,3:45" },
{ "slots": "4:30,5:30,6:30,7:30,8:30,9:30,10:30,11:30" }
]
}
]
}
}`
And I want below output using nodejs:
`{ "available_slots":
[ {
"slot1": "2:45-3:45",
"slot2": "4:30-5:30",
"slot3": "5:30-6:30",
"slot4": "6:30-7:30" }
]
}`
I have coded below function to retrieve the above output but it gives only one slot data
function divideIntoSlots(slots) {
var mainSlots = {
"available_slots" :
[
{ "slot1" : "", "slot2" : "", "slot3" : "", "slot4" : ""
} ]
};
var i = 1;
slots.available_slots.forEach( function(slot) {
var mainS = slot.slots;
if(mainS.indexOf(',') > -1) {
mainS = mainS.split(',');
var newMain;
if(i==1){
newMain = mainS[0]+"-"+mainS[1];
mainSlots.available_slots[0].slot1 = newMain;
}
i++;
}
});
return mainSlots;
}
divideIntoSlots(slots)
OutPut:
`{ "available_slots":
[ {
"slot1": "2:45-3:45",
"slot2": "",
"slot3": "",
"slot4": "" }
]
}`
Anyone, please help me to short out this issue to resolve.
You can use reduce to summarise your data. Use forEach to loop thru the array,
var data = {"data":{"2018-08-21":[{"available_slots":[{"slots":"1.15"},{"slots":"2:45,3:45"},{"slots":"4:30,5:30,6:30,7:30,8:30,9:30,10:30,11:30"}]}]}}
function divideIntoSlots(slots) {
var mainSlots = {"available_slots": []};
var s = slots.available_slots.reduce((c, v) => {
v.slots.split(',').forEach((o, i, a) => {
if (c.length < 4 && a[i + 1]) c.push(o + "-" + a[i + 1]);
});
return c;
}, []).reduce((c, v, i) => Object.assign(c, {["slot" + (i + 1)]: v}), {});
mainSlots.available_slots.push(s);
return mainSlots;
}
var result = divideIntoSlots(data.data['2018-08-21'][0])
console.log(result);
Probably you want that:
function divideIntoSlots(slots) {
var mainSlots = {
"available_slots": [{
"slot1": "",
"slot2": "",
"slot3": "",
"slot4": ""
}]
};
let i = 1;
slots.available_slots.forEach(function(slot) {
var mainS = slot.slots;
if (mainS.indexOf(',') > -1 && mainSlots.available_slots[0].hasOwnProperty('slot' + i)) {
var newSlots = mainS.replace(/(\d+:\d+),(\d+:\d+)/g, "$1-$2")
newSlots = newSlots.split(",");
if (newSlots.length > 1) {
newSlots.forEach(e => {
if (!mainSlots.available_slots[0].hasOwnProperty("slot" + i))
return;
mainSlots.available_slots[0]["slot" + i] = e;
i++;
});
} else {
mainSlots.available_slots[0]["slot" + i] = newSlots[0];
i++
}
}
});
return mainSlots;
}
console.log(divideIntoSlots({
"available_slots": [{
"slots": "1:15"
},
{
"slots": "2:45,3:45"
},
{
"slots": "4:30,5:30,6:30,7:30,8:30,9:30,10:30,11:30"
}
]
}));

How to convert following Json object as a string like below

I have a json object as follows,
{
"category": "music",
"location": {
"city": "Braga"
},
"date": {
"start": {
"$gte": "2017-05-01T18:30:00.000Z"
},
"end": {
"$lt": "2017-05-12T18:30:00.000Z"
}
}
}
i need to create a query string as follows,
category=music | location.city = Braga | date.start.$gte = 2017-05-01T18:30:00.000Z | date.end.$lt = 2017-05-12T18:30:00.000Z
How can I achieve this?
This is what i have tried.
_.each(this.filter, (val: string, key: string) => {
if (key && val) {
filterArray.push(`${key}=${val}`);
}
});
You could iterate the keys and build a path to the value. Later join pathes and add value and join to the final string.
function getParts(object) {
function iter(o, p) {
Object.keys(o).forEach(function (k) {
if (o[k] && typeof o[k] === 'object') {
iter(o[k], p.concat(k));
return;
}
result.push(p.concat(k).join('.') + ' = ' + o[k]);
});
}
var result = [];
iter(object, []);
return result.join(' | ');
}
var object = { "category": "music", "location": { "city": "Braga" }, "date": { "start": { "$gte": "2017-05-01T18:30:00.000Z" }, "end": { "$lt": "2017-05-12T18:30:00.000Z" } } },
string = getParts(object);
console.log(string);
Sorry, I'm late, but still.
Method walk recursively runs through your JSON and calls callback function with chain of keys and value as arguments.
Then convert uses walk to translate JSON into your format:
var walk = function( data, iterator, stack ) {
var key;
stack = stack || [];
for ( key in data ) {
if ( typeof data[ key ] === 'string' ) {
iterator( stack.concat( [ key ] ), data[ key ] );
} else {
walk( data[ key ], iterator, stack.concat( [ key ] ) );
}
}
};
var convert = function( data ) {
var result = [];
walk( data, function( keys, value ) {
result.push( keys.join( '.' ) + ' = ' + value );
} );
return result.join( ' | ' );
};
var query_string = convert( /* your JSON here */ );

To print all the paths in a json object

What is the easy way to get all paths in the Given Json Object;
For Example:
{
app:{
profiles:'default'
},
application:{
name:'Master Service',
id:'server-master'
},
server:{
protocol:'http',
host:'localhost',
port:8098,
context:null
}
}
I should able to produce the following object
app.profiles=default
application.name=Master Service
application.id=server-master
I was able to achieve the same using a recursive function. I want to know is there any built in function from json which does this.
You can implement your custom converter by iterating through objects recursively.
Something like this:
var YsakON = { // YsakObjectNotation
stringify: function(o, prefix) {
prefix = prefix || 'root';
switch (typeof o)
{
case 'object':
if (Array.isArray(o))
return prefix + '=' + JSON.stringify(o) + '\n';
var output = "";
for (var k in o)
{
if (o.hasOwnProperty(k))
output += this.stringify(o[k], prefix + '.' + k);
}
return output;
case 'function':
return "";
default:
return prefix + '=' + o + '\n';
}
}
};
var o = {
a: 1,
b: true,
c: {
d: [1, 2, 3]
},
calc: 1+2+3,
f: function(x) { // ignored
}
};
document.body.innerText = YsakON.stringify(o, 'o');
That's not a best converter implementation, just a fast-written example, but it should help you to understand the main principle.
Here is the working JSFiddle demo.
I think there is no built-in function that does this. It can be done with a simple for loop as below in my fiddle. But it does not take care of recursiveness. Here are other posts that i found regarding the same : Post1 and Post2 and Post3
var myjson = {
app:{
profiles:'default'
},
application:{
name:'Master Service',
id:'server-master'
},
server:{
protocol:'http',
host:'localhost',
port:8098,
context:null
}
};
for(key in myjson) {
for(k in myjson[key]) {
console.log(key + '.' + k + ' = '+ myjson[key][k]);
}
}
Fiddle
var obj1 = {
"name" : "jane",
"job" : {
"first" : "nurse",
"second" : "bartender",
"last" : {
"location" : "Paris",
"work" : ["sleep", "eat", "fish", {"math" : "morning", "chem" : "late night"}],
"read_books": {
"duration" : 10,
"books_read" : [{"title" : "Gone with the wind", "author": "I don't know"}, {"title": "Twologht", "author": "Some guy"}]
}
}
},
"pets": ["cow", "horse", "mr. peanutbutter"],
"bf" : ["jake", "beatles", {"johnson": ["big johnson", "lil johnson"]}]
}
var obj2 = ["jane", "jake", {"age" : 900, "location": "north pole", "name" : "Jim", "pets" : "..."}];
var allRoutes = [];
function findTree(o, parentKey = '', parentObject)
{
if (typeof o !== 'object')
{
if (parentKey.substr(0,1) === '.')
allRoutes.push(parentKey.substr(1));
else
allRoutes.push(parentKey);
return;
}
let keys = Object.keys(o);
for (let k in keys)
{
findTree(o[keys[k]], Array.isArray(o) ? parentKey + "[" +keys[k] + "]" : parentKey + "." +keys[k], o);
//findTree(o[keys[k]], parentKey + "[" +keys[k] + "]");
}
}
findTree(obj1);
Try this.

Categories