How do I translate javascript object to a new object? - javascript

I need to import a few external json data into a variable or into a single json file to then display that data with D3.
This is the format of the data that I need to import from each json file:
{
"name": "name1",
"version": "0.1.2",
"references": [
{
"url1": "http://example1.com"
},
{
"url2": "http://example2.com"
}
]
}
And this is the format of data that I need for the final json file/variable.
{
"nodes":[
{
"name": "name1",
"version": "0.1.2",
"references": [
{
"url1": "http://example1.com"
},
{
"url2": "http://example2.com""
}
]
},
{
"name": "name2",
"version": "1.6.0",
"references": [
{
"url1": "http://example34.com"
},
{
"url2": "http://example30.com""
}
]
},
{
...
...
}
],
"links":[
]
}
Basically I need to merge the data from the different json files inside the "nodes" array.
Any idea how could I do this?
Thanks

nodes is a simple array, so you can just push the 'file' objects into the nodes array.
var file1 = {
"name": "name1",
"version": "0.1.2",
"references": [
{
"url1": "http://example1.com"
},
{
"url2": "http://example2.com"
}
]
}
var file2 = {
"name": "name1",
"version": "0.1.2",
"references": [
{
"url1": "http://example1.com"
},
{
"url2": "http://example2.com"
}
]
}
var files = [file1, file2];
var node = {
"nodes": [],
"links": []
}
files.forEach(function(file) {
node.nodes.push(file);
})
console.log(node);

If you simply need to push all the data from the imported JSON into nodes, you can do this:
var imported = {
"name": "name1",
"version": "0.1.2",
"references": [
{
"url1": "http://example1.com"
},
{
"url2": "http://example2.com"
}
]
};
var finalJson = {
nodes: []
};
finalJson.nodes.push(imported);
Here is the fiddle: https://jsfiddle.net/vj1nqeu5/1/

Related

Flattening an array of objects based on specific keys

I am currently making a tree view, where there will be folders and subfolders.
The code is as such from my json file:
[
{
"name": "Knowledge Base",
"files": [
"knowledge-base.pdf",
"hello-word.pdf"
],
"folders": [
{
"name": "Documents",
"files": [
"file1.pdf",
"file2.pdf",
"file3.pdf"
],
"folders": [
{
"name": "Important Documents",
"files": [
"I like trains",
"Why",
"OMG NOOOO"
],
"folders": [
{
"name": "Hello World",
"files": [
"Hell no"
]
}
]
},
{
"name": "My secrets",
"files": [
"Pay",
"I dont like my boss",
"Hobbies"
]
}
]
},
{
"name": "Images",
"files": [
"image1.png",
"image2.png",
"image3.png",
"image4.png",
"image5.png"
],
"folders": ""
},
{
"name": "Important",
"files": [
"confidential.pdf",
"important.pdf"
],
"folders": ""
}
]
},
{
"name": "Downloads",
"files": [
"download1.pdf",
"download2.pdf",
"download3.pdf"
],
"folders": ""
},
{
"name": "Favourites",
"files": [
"favourite1.pdf",
"favourite2.pdf",
"favourite3.pdf",
"favourite4.pdf"
],
"folders": ""
}
]
A new folder is denoted with a new object {}, which consists of its name, files and folders within it, if any.
I would like to flatten the dictionary such that it outputs all files (with a file is denoted by a . and a folder is denoted by a >:
For example, for the documents folder:
Knowledge Base>Documents.file1.pdf
Knowledge Base>Documents.file2.pdf
Knowledge Base>Documents.file3.pdf
Knowledge Base>Documents>Important Documents.I like trains
Knowledge Base>Documents>Important Documents.Why
Knowledge Base>Documents>Important Documents.OMG NOOOO
Knowledge Base>Documents>Important Documents>Hello World.Hell no
Knowledge Base>Documents>My Secrets.I dont like my boss
Knowledge Base>Documents>My Secrets.Hobbies
You can use a basic recusrive function like this:
const tree = [{
"name": "Knowledge Base",
"files": [
"knowledge-base.pdf",
"hello-word.pdf"
],
"folders": [{
"name": "Documents",
"files": [
"file1.pdf",
"file2.pdf",
"file3.pdf"
],
"folders": [{
"name": "Important Documents",
"files": [
"I like trains",
"Why",
"OMG NOOOO"
],
"folders": [{
"name": "Hello World",
"files": [
"Hell no"
]
}]
},
{
"name": "My secrets",
"files": [
"Pay",
"I dont like my boss",
"Hobbies"
]
}
]
},
{
"name": "Images",
"files": [
"image1.png",
"image2.png",
"image3.png",
"image4.png",
"image5.png"
],
"folders": ""
},
{
"name": "Important",
"files": [
"confidential.pdf",
"important.pdf"
],
"folders": ""
}
]
},
{
"name": "Downloads",
"files": [
"download1.pdf",
"download2.pdf",
"download3.pdf"
],
"folders": ""
},
{
"name": "Favourites",
"files": [
"favourite1.pdf",
"favourite2.pdf",
"favourite3.pdf",
"favourite4.pdf"
],
"folders": ""
}
]
var result = []
function rec(folders, acc) {
if (folders) {
folders.forEach(folder => {
const newAcc = !!acc ? `${acc}>${folder.name}` : `${folder.name}`
if (folder.files) {
const newFiles = folder.files.map(file => `${newAcc}.${file}`)
result = [...result, ...newFiles]
}
if (folder.folders) {
rec(folder.folders, newAcc)
}
})
}
}
rec(tree, '')
console.log(result)
For that you need to do a recursive identifying when it is an array, a folder or a file.
const treeView = [
{
name: "Knowledge Base",
files: [
"knowledge-base.pdf",
"hello-word.pdf"
],
folders: [
{
name: "Documents",
files: [
"file1.pdf",
"file2.pdf",
"file3.pdf"
],
folders: [
{
name: "Important Documents",
files: [
"I like trains",
"Why",
"OMG NOOOO"
],
folders: [
{
name: "Hello World",
files: [
"Hell no"
]
}
]
},
{
name: "My secrets",
files: [
"Pay",
"I dont like my boss",
"Hobbies"
]
}
]
},
{
name: "Images",
files: [
"image1.png",
"image2.png",
"image3.png",
"image4.png",
"image5.png"
],
folders: ""
},
{
name: "Important",
files: [
"confidential.pdf",
"important.pdf"
],
folders: ""
}
]
},
{
name: "Downloads",
files: [
"download1.pdf",
"download2.pdf",
"download3.pdf"
],
folders: ""
},
{
name: "Favourites",
files: [
"favourite1.pdf",
"favourite2.pdf",
"favourite3.pdf",
"favourite4.pdf"
],
folders: ""
}
]
function handleObj(obj, type, path = '') {
const result = []
if (Array.isArray(obj)) { // recursive on arrays
for (const thisObj of obj) {
result.push(handleObj(thisObj, type, path))
}
} else {
type = type || getType(obj)
if (type === 'folder') { // recursive on folders
const {
name,
files,
folders
} = obj
path = path ? `${path}>${name}` : name
if (files && files.length) {
result.push(handleObj(files, 'file', path))
}
if (folders && folders.length) {
result.push(handleObj(folders, 'folder', path))
}
} else if (type === 'file') {
const filename = obj
if (path) {
result.push(`${path}.${filename}`)
} else {
result.push(`${filename}`)
}
}
}
return result.join('\n')
}
function getType(obj) {
const {
name,
files,
folders
} = obj
if (name !== undefined && files !== undefined && folders !== undefined) {
return 'folder'
}
return 'file'
}
console.log(handleObj(treeView))
Recursive function is to the resqueue.
The idea behind recursive function is that it accepts an object as parameter and if a child of that object contains folders, loop through array of these folders and send each folder object back to the same function.
const data = [
{
"name": "Knowledge Base",
"files": [
"knowledge-base.pdf",
"hello-word.pdf"
],
"folders": [
{
"name": "Documents",
"files": [
"file1.pdf",
"file2.pdf",
"file3.pdf"
],
"folders": [
{
"name": "Important Documents",
"files": [
"I like trains",
"Why",
"OMG NOOOO"
],
"folders": [
{
"name": "Hello World",
"files": [
"Hell no"
]
}
]
},
{
"name": "My secrets",
"files": [
"Pay",
"I dont like my boss",
"Hobbies"
]
}
]
},
{
"name": "Images",
"files": [
"image1.png",
"image2.png",
"image3.png",
"image4.png",
"image5.png"
],
"folders": ""
},
{
"name": "Important",
"files": [
"confidential.pdf",
"important.pdf"
],
"folders": ""
}
]
},
{
"name": "Downloads",
"files": [
"download1.pdf",
"download2.pdf",
"download3.pdf"
],
"folders": ""
},
{
"name": "Favourites",
"files": [
"favourite1.pdf",
"favourite2.pdf",
"favourite3.pdf",
"favourite4.pdf"
],
"folders": ""
}
];
function flatten(obj, parent = "")
{
parent += obj.name; //append current folder name
let result = obj.files ? obj.files.map(file => parent + "." + file) : [];//add files
if (Array.isArray(obj.folders))
result = result.concat(...obj.folders.map(folder => flatten(folder, parent + ">"))); //recursivly call flatten for next subfolder
return result;
}
const dataFlat = data.reduce((a,b) => (a.push(...flatten(b)), a), []);
console.log(dataFlat);
.as-console-wrapper{top:0;max-height:unset!important;overflow:auto!important;}

javascript print nested array to screen

I have a data array, there are multiple objects in this array, and the data object is an array. There may be more than one object in this array. How can I copy these objects under a single array?
const test = []
const data = [
{
"_id": "124141",
"name": "test",
"data": [
{
"price":10,
"title": "sda"
},
]
},
{
"_id": "2525",
"name": "test2",
"data": [
{
"price":20,
"title": "asdas"
},
]
}
]
[{
"price":10,
"title": "sda"
},
{
"price":20,
"title": "asdas"
},
]
If this is the output I expect, it should be like this. how can I do that
const data = [
{
"_id": "124141",
"name": "test",
"data": [
{
"price":10,
"title": "sda"
},
{
"price":99,
"title":"aaaaa"
}
]
},
{
"_id": "2525",
"name": "test2",
"data": [
{
"price":20,
"title": "asdas"
},
]
}
];
console.log(data.map(e => e.data).flat());
// OR
console.log(data.flatMap(e => e.data));

how to push a data with key of an array of objects without overwriting existing json data using node js?

I have an object that looks like this :
{
"mark": [
{
"id":1,
"name": "mark",
"age":26
},
{
"id":2,
"name": "mark",
"age":25
}
],
"jack": [
{
"id":1,
"name": "jack",
"age":26
},
{
"id":2,
"name": "jack",
"age": 24,
}
]
}
WHAT I GOT AS OUTPUT IF A NEW USER IS ADDED IT IS NOT APPENDED, BUT IT IS OVERWRITTEN OR CREATED AS A NEW OBJECT
{
"mark": [
{
"id":1,
"name": "mark",
"age":26
},
{
"id":2,
"name": "mark",
"age":25
}
],
"jack": [
{
"id":1,
"name": "jack",
"age":26
},
{
"id":2,
"name": "jack",
"age": 24,
}
],
} "Josh": [
{
"id":1,
"name": "Josh",
"age":26
},
{
"id":2,
"name": "Josh",
"age": 24,
}
]
Expected
if new person data arrives in my JSON File, that should be appended to the next array with key values of array of Objects,
like
{
"mark": [
{
"id":1,
"name": "mark",
"age":26
},
{
"id":2,
"name": "mark",
"age":25
}
],
"jack": [
{
"id":1,
"name": "jack",
"age":26
},
{
"id":2,
"name": "jack",
"age": 24,
}
],
"Josh": [
{
"id":1,
"name": "Josh",
"age":26
},
{
"id":2,
"name": "Josh",
"age": 24,
}
]
}
I've tried this method after reading the JSON file
var newObject = array.reduce(function (obj, value) {
var key = `${value.name}`;
if (obj[key] == null) obj[key] = [];
obj[key].push(value);
return obj;
}, {});
console.log(newObject);
fs.appendFile("users.json", newObject, (err) => {
res.send(JSON.stringify(newObject));
});
Like the advice already given, but using async fs i/o.
import { promises as fs } from 'fs'; // or require('fs').promises
// inside the OP's route
const filename = 'users.json';
try {
const array = await fs.readFile(filename);
// OP's code here
// const newObject = array.reduce(...
await fs.writeFile(filename, newObject);
return res.send(JSON.stringify(newObject));
} catch (error) {
return res.status(500).send({ message: 'error' });
}
Also note that all this is what a database does.
You have to first read the data from the JSON and append the new object to the JSON data and then write it back to the file.
const data = fs.readFileSync('users.json');
.
.
fs.writeFileSync('users.json', {...data, ...newObject});

Apply custom colors to only specific output channel

How can I add custom colors to only output channel created by my extension?
Currently I have this package.json
{
"name": "mytestextension-output-colors",
"displayName": "My test extension - output colors",
"version": "0.0.1",
"publisher": "nobody",
"engines": {
"vscode": "^1.72.0"
},
"main": "./extension.js",
"activationEvents": [
"onStartupFinished"
],
"contributes": {
"languages": [
{
"id": "mytestextension-output",
"aliases": [],
"mimetypes": [
"text/x-code-output"
]
}
],
"grammars": [
{
"language": "mytestextension-output",
"scopeName": "text.mytestextension-output",
"path": "./mytestextension-output.tmLanguage.json"
}
],
"configuration": {
"type": "object",
"title": "My Test Extension - output colors"
},
"configurationDefaults": {
"editor.tokenColorCustomizations": {
"textMateRules": [
{
"scope": "mytestextension-output-red",
"settings": {
"foreground": "#f00080"
}
}
]
}
}
}
}
extension.js
const window = require("vscode").window;
function activate() {
const out = window.createOutputChannel("myextension test output", "mytestextension-output");
out.appendLine(`red output`);
}
function deactivate() {}
module.exports = {
activate,
deactivate
};
mytestextension-output.tmLanguage.json
{
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
"name": "mytestextension-output",
"scopeName": "text.mytestextension-output",
"patterns": [ {
"match": ".*",
"name": "mytestextension-output-red"
}
]
}
Even though the grammar is set for mytestextension-output id/scope, it applied to and changes color to red in all output channels (git, tasks, extensions, etc)
What am I missing here?
Gist example

JavaScript :: Iterate through nested JSON object and create new structure

Attempting to restructure nested JSON data (data1) into "proper" format (data2)
with no success so far.
data1 is generated based on a given parent directory (recipes) that looks for html files.
data2 is what I'm trying to output using data1 since whatever content inside a folder is better represented as array of objects than just pure nested objects.
var data1 = {
"cake": {
"chocolate": {
"black-forest": {
"name": "Black Forest",
"path": "recipes/cake/chocolate/black-forest.html"
},
"new-shortcake": {
"milk-chocolate-shortcake": {
"name": "Milk chocolate shortcake",
"path": "recipes/cake/chocolate/shortcake/milk-chocolate-shortcake.html"
},
"dark-chocolate-shortcake": {
"name": "Dark chocolate shortcake",
"path": "recipes/cake/chocolate/shortcake/dark-chocolate-shortcake.html"
}
}
}
},
"pasta": {
"spaghetti": {
"aglio-olio": {
"name": "Spagehetti Aglio Olio",
"path": "recipes/pasta/spaghetti/aglio-olio.html"
},
"carbonara": {
"name": "Carbonara",
"path": "recipes/pasta/spaghetti/carbonara.html"
}
},
"lasagna": {
"name": "Lasagna",
"path": "recipes/pasta/lasagna.html"
}
}
}
var data2 = [
{
"name": "cake",
"children": [
{
"name": "chocolate",
"children": [
{
"name": "Black Forest",
"path": "recipes/cake/chocolate/black-forest.html"
},
{
"name": "New Shortcake",
"children": [
{
"name": "Milk chocolate shortcake",
"path": "recipes/cake/chocolate/shortcake/milk-chocolate-shortcake. html"
},
{
"name": "Dark chocolate shortcake",
"path": "recipes/cake/chocolate/shortcake/dark-chocolate-shortcake. html"
}
]
}
]
}
]
},
{
"name": "pasta",
"children": [
{
"name": "spaghetti",
"children": [
{
"name": "Spagehetti Aglio Olio",
"path": "recipes/pasta/spaghetti/aglio-olio.html"
},
{
"name": "Carbonara",
"path": "recipes/pasta/spaghetti/carbonara.html"
}
]
},
{
"name": "Lasagna",
"path": "recipes/pasta/lasagna.html"
}
]
}
]
https://codepen.io/kyooriouskoala/pen/LLLXmG
Any help much appreciated!
PS: End goal is to build a menu with the new data structure.
I hope this output is what you meant.
var final = [];
function tree(object, temp){
for(var key in object){
var folder = {};
if(object[key] !== null && typeof object[key] == 'object'){
//console.log(key);
if(_.has(object[key], "path")){
folder.name = object[key].name;
folder.path = object[key].path;
folder.children = [];
} else{
folder.name = key;
folder.children = object[key];
}
final.push(folder);
tree(object[key]);
}
}
return final;
}
This outputs your data as a associative object with values needed.

Categories

Resources