Is there a similar method to array.push that one can use to inject a new node into a json object?
I have an endpoint that requires a payload with dynamic element names based on what is being passed in, so i need to scrape the array and insert it into the payload for the correct format.
Example of the end-result payload i need:
{
"fields": {
"project": {
"key": projectKey
},
"summary": summary,
"description": description,
"issuetype": {
"name": issueType
},
"customfield_123456": "value1",
"customfield_7890": "value2"
}
}
This is the function in the controller that consumes the request body and attempts to inject the values in the customFields Array as elements in the json object but is not working:
const createIssueApi = async(req, res, next) => {
try {
let {
projectKey,
summary,
description,
issueType,
customFields
} = req.body;
console.log(req.body)
let jiraIssue = {
"fields": {
"project": {
"key": projectKey
},
"summary": summary,
"description": description,
"issuetype": {
"name": issueType
}
}
}
for (let ix = 0; ix < customFields.length; ix++) {
jiraIssue.fields[$ {
customFields[ix]
}] = customFields[ix];
}
console.log("Jira Issue payload: ", jiraIssue)
} catch (e) {
console.log(e)
}
}
This is the payload being sent in:
{
"projectKey": "JK",
"summary": "summary text",
"description": "THIS IS JUST A TEST",
"issueType": "Submit a request or incident",
"customFields": [{
"customfield_123456": "value1"
},
{
"customfield_7890": "value2"
}
]
}
there are methods
Array.prototype.push()
Array.prototype.pop()
Array.prototype.shift()
Array.prototype.unshift()
Array.prototype.concat()
for instance
const animals = ['pigs', 'goats', 'sheep'];
const count = animals.push('cows');
console.log(count);
// expected output: 4
console.log(animals);
// expected output: Array ["pigs", "goats", "sheep", "cows"]
animals.push('chickens', 'cats', 'dogs');
console.log(animals);
// expected output: Array ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"]
You appear to be attempting to use the same value for both the name and the value, and your Js seems to be invalid in that spot - [$ { is not valid js, but something like this should work
jiraIssue.fields[`customFields_${ix}`] = customFields[ix];
You can try using for...of and Object.entries inside for
const customFields = [{
'customfield_123456': 'value1'
},
{
'customfield_7890': 'value2'
}
];
const jiraIssue = {'fields': {}};
for (let ix = 0; ix < customFields.length; ix++) {
for (const [key, val] of Object.entries(customFields[ix])) {
jiraIssue.fields[key] = val;
}
}
console.log(jiraIssue);
The following is an example used with reduce
const restructure = (req) => {
const {customFields, ...rest} = req.body;
const fields = {
'project': {
"key": rest['projectKey']
},
'summary': rest['summary'],
'description': rest['description'],
'issuetype': {
"name": rest['issueType']
}
};
customFields.reduce((accumu, current) => {
for (const [key, val] of Object.entries(current)) {
accumu[key] = val;
}
return accumu;
}, fields);
return {fields};
}
const req = {
"body": {
"projectKey": "JK",
"summary": "summary text",
"description": "THIS IS JUST A TEST",
"issueType": "Submit a request or incident",
"customFields": [{
"customfield_123456": "value1"
},
{
"customfield_7890": "value2"
}
]
}
};
console.log(restructure(req));
Related
I am trying to move everything in the Array Results outside and into the original object
this is the object
{
"Name": "John",
"Results": [
{
"Type": "DB",
"Immediate_Action": "No",
}
]
}
It should look like this
{
"Name": "John",
"Type": "DB",
"Immediate_Action": "No",
}
What I have so far is this
const mapOscarResults = ({ data }) => {
return data.map(entry => {
let mapped = {...entry};
entry.Results.forEach(key => {
let Type = mapped[key.Type]
if (mapped[key]) {
mapped[key].push(entry.Results[key]);
} else {
mapped[key] = [entry.Results[key]];
}
});
return mapped;
});
};
You can simply spread the Results array into an Object.assign() call.
const input = { "Name": "John", "Results": [{ "Type": "DB", "Immediate_Action": "No", }, { "Another": "value" }] };
const { Results, ...refactored } = input;
Object.assign(refactored, ...Results);
console.log(refactored)
This code works for your example:
const { Results: results, ...rest } = {
"Name": "John",
"Results": [
{
"Type": "DB",
"Immediate_Action": "No",
}
]
}
const res = {...rest, ...results.reduce((prev, curr) => ({
...prev,
...curr
}), {})}
console.log(res)
But I don't know what you expect when the Results array has more than one element.
In that condition, if this code does not fill your needs, ask me to change it.
however, it will join first Result with index 0, you can expand it
const data = {
"Name": "John",
"Results": [
{
"Type": "DB",
"Immediate_Action": "No",
}
]
}
const mapOscarResults = (data) => {
for (let i in Object.keys(data)){
if (Array.isArray(data[Object.keys(data)[i]])){
newKey = data[Object.keys(data)[i]][0]
data = {... data, ...newKey}
delete data[Object.keys(data)[i]]
}
}
return data
};
console.log(mapOscarResults(data))
i have response data like this
{
"data": {
"title": "dashboard",
"description": "just test dashboard",
"photos": [
{
"file_name": "12345454.jpg",
"photo_name": "indonesia"
},
{
"file_name": "567686.jpg",
"photo_name": "jakarta"
}]
}
}
then i need change response of data with file_name of array without photos variable.
expected: file_name[0] will be sign from file_name index of array
like this
{
"data": {
"title": "dashboard",
"description": "just test dashboard",
"file_name[0]": "12345454.jpg",
"file_name[1]": "567686.jpg"
}
}
i have try with map of photos but didn't work
this.data = this.data.photos.map((item, idx) => {
let data = {
file_name: item.file_name
}
return data
})
this.data.photos.map((item, idx) => {
this.$set(this.data, 'file_name', item.file_name)
})
Try following
let data = {"title": "dashboard","description": "just test dashboard","photos":[{"file_name": "12345454.jpg","photo_name": "indonesia"},{"file_name": "567686.jpg","photo_name": "jakarta"}]};
data.photos.forEach((v,i) => data[`file_name[${i}]`] = v.file_name);
delete data.photos;
console.log(data);
I propose a soluce creating a new object.
#Nikhil Aggarwal soluce mutate the existing object
Both are good, pick your poison :)
const old = {
data: {
title: 'dashboard',
description: 'just test dashboard',
photos: [
{
file_name: '12345454.jpg',
photo_name: 'indonesia',
},
{
file_name: '567686.jpg',
photo_name: 'jakarta',
}],
},
};
const formatted = {
// We use reduce to create the data object
data: Object.keys(old.data).reduce((tmp, x) => {
// If we are not dealing with photos key, just add the old data to the new object
if (x !== 'photos') {
tmp[x] = old.data[x];
return tmp;
}
// for each photo, add a new key
old.data.photos.forEach((y, yi) => {
tmp[`file_name[${yi}]`] = y.file_name;
});
return tmp;
}, {}),
};
console.log(formatted);
If I understand correctly, you actually want file_name to be an array. If so, and you are happy to alter the object in place, try:
const obj = {
data: {
title: 'dashboard',
description: 'just test dashboard',
photos: [
{
file_name: '12345454.jpg',
photo_name: 'indonesia'
},
{
file_name: '567686.jpg',
photo_name: 'jakarta'
}]
},
}
obj.data.file_name = obj.data.photos.map(i => i.file_name)
delete obj.data.photos
console.log(obj)
have a look at this example. by using this you can restructure or create new you json.
<span id="text"></span><br/>
<span id="photosdata"></span>
here is the logic
var obj = JSON.parse('{ "data": { "title": "dashboard", "description": "just test dashboard", "photos": [ { "file_name": "12345454.jpg", "photo_name": "indonesia" }, { "file_name": "567686.jpg", "photo_name": "jakarta" }] } }');
document.getElementById("text").innerHTML = obj.data.title+"<br/>";
var photos = obj.data.photos;
photos.forEach(function(item){
document.getElementById("text").innerHTML += item.file_name +"<br/>";
});
https://jsfiddle.net/qufnwmd4/1/
How can I get the names of different activity in an array by using map function in this type of response. So that in a new array, assume that activity[] i will get names of all the activities mention below.
if the array is
const response = [
{
"Groups" : {
"Roles" : {
"submission": {
"subject" : {
"name": "history",
}
}
}
}
}
];
I managed to do this using an IIFE but there may be cleaner ways
assuming there in one object in the array and no other path to other permission
const response = [
{
"Roles" : {
"Permission" : {
"PERMISSION1": {
"Activity" : {
"name": "Manage Clients",
}
},
"PERMISSION2": {
"Activity" : {
"name": "Manage Users",
}
}
}
}
}
];
let activities = (() => {
let res = []
for (let perm in response[0].Roles.Permission) {
for (let act in response[0].Roles.Permission[perm]) {
res.push(response[0].Roles.Permission[perm][act].name)
}
}
return res})()
console.log(activities)
At first, you should convert Permission object to array, cause object doesn't have method map.
Then you could use map function where you can collect all your permissions' names for every item in response
const response = [{
"Roles": {
"Permission": {
"PERMISSION1": {
"Activity": {
"name": "Manage Clients",
}
},
"PERMISSION2": {
"Activity": {
"name": "Manage Users",
}
}
}
}
}];
response.forEach((item) => {
item.Activities = Object.values(item.Roles.Permission).map((permission) => permission.Activity.name)
});
alert(JSON.stringify(response));
The only array you have is response. If each item in response has a Roles that has a Permission that has several keys with objects that have Activity with name then you can do the following:
var response = [
{
Roles: {
Permission: {
PERMISSION1: {
Activity: {
name: 'Manage Clients',
},
},
PERMISSION2: {
Activity: {
name: 'Manage Users',
},
},
},
},
},
];
console.log(
response.map(
(item) =>
Object.values(item.Roles.Permission)
.map(
(permission) => permission.Activity.name
)
)
);
I recommend using a flatMap, so use .reduce.
const response = [{
"Roles": {
"Permission": {
"PERMISSION1": {
"Activity": {
"name": "Manage Clients",
}
},
"PERMISSION2": {
"Activity": {
"name": "Manage Users",
}
}
}
}
}];
const activityNames = response.reduce(function (acc, res) {
const permissions = res.Roles.Permission;
const permissionKeys = Object.keys(permissions);
const names = permissionKeys.map(function(permissionKey) {
return permissions[permissionKey].Activity.name;
});
acc.push(...names);
return acc;
}, [])
console.log(activityNames); // ["Manage Clients", "Manage Users"]
I have an array of data. Some of the key in the array are same. I would like to create a new array based on the key and add the other data.
This is my array
var myObjOne = [
{
"name":"John",
"id":1,
"car":"maruti"
},
{
"name":"John",
"id":2,
"car":"wolks"
},
{
"name":"John",
"id":3,
"car":"bmw"
},
{
"name":"Peter",
"id":4,
"car":"alto"
},
{
"name":"Peter",
"id":5,
"car":"swift"
}
];
I would like to convert the array in to the below format.
var myObj = [
{
"name":"John",
"items": [
{ "id":1, "car":"maruti" },
{ "id":2, "car":"wolks" },
{ "id":3, "car":"bmw" }
]},
{
"name":"Peter",
"items": [
{ "id":4, "car":"alto" },
{ "id":5, "car":"swift" },
]
}
];
I am working on a node environment.
You can create an object using Array#reduce first which maps name with items, and then create the final array by looping over the intermediate map using a for...of loop:
var source = [{"name":"John","id":1,"car":"maruti"},{"name":"John","id":2,"car":"wolks"},{"name":"John","id":3,"car":"bmw"},{"name":"Peter","id":4,"cars":"alto"},{"name":"Peter","id":5,"cars":"swift"}];
const map = source.reduce((acc, {name, ...obj}) => {
if (!acc[name]) {
acc[name] = [];
}
acc[name].push(obj);
return acc;
}, {});
const result = [];
for (let[name, items] of Object.entries(map)) {
result.push({name, items});
}
console.log(result);
Array.reduce is at rescue.This method accepts an accumulator and current
item. Check in the accumulator if there exist an object where the value of name property is John or Peter
var myObjOne = [{
"name": "John",
"id": 1,
"car": "maruti"
},
{
"name": "John",
"id": 2,
"car": "wolks"
},
{
"name": "John",
"id": 3,
"car": "bmw"
},
{
"name": "Peter",
"id": 4,
"car": "alto"
},
{
"name": "Peter",
"id": 5,
"car": "swift"
}
];
var newObj = myObjOne.reduce(function(acc, curr, currIndex) {
// using findIndex to check if there exist an object
// where the value of the name property is John, Peter
// if it exist it will return the index else it will return -1
let ifNameExist = acc.findIndex(function(item) {
return item.name === curr.name;
})
// if -1 then create a object with name and item property and push
// it to the accumulator
if (ifNameExist === -1) {
let nameObj = {};
nameObj.name = curr.name;
nameObj.items = [];
nameObj.items.push({
id: curr.id,
car: curr.car
})
acc.push(nameObj)
} else {
// if such an object already exist then just update the item array
acc[ifNameExist].items.push({
id: curr.id,
car: curr.car
})
}
return acc;
}, []);
console.log(newObj)
Use .reduce to group by name, and use .find inside the reducer to find if the matching name has already been added:
const input=[{"name":"John","id":1,"car":"maruti"},{"name":"John","id":2,"car":"wolks"},{"name":"John","id":3,"car":"bmw"},{"name":"Peter","id":4,"cars":"alto"},{"name":"Peter","id":5,"cars":"swift"}]
const output = input.reduce((a, { name, ...item }) => {
const foundNameObj = a.find(nameObj => nameObj.name === name);
if (foundNameObj) foundNameObj.items.push(item);
else a.push({ name, items: [item] });
return a;
}, []);
console.log(output);
I am trying to add element "delete:true" after each occurrence of "_rev " mentioned in the below sample request.
Original Request:
{
"docs": [
{
"_id": "123",
"_rev": "1-7836",
},
{
"_id": "456",
"_rev": "1-1192",
}
]
}
Expected Request:
{
"docs": [
{
"_id": "123",
"_rev": "1-7836",
"_deleted" :true
},
{
"_id": "456",
"_rev": "1-1192",
"_deleted" :true
}
]
}
When I tried the below code,the ""_deleted" :true" is getting inserted after the -rev element is closed. PFB for the same and suggest.
function main(params) {
for (var i = 0; i< params.docs.length; i++) {
for (var value in params.docs[i]) {
if(value == '_rev' && params.docs[i]._rev ){
var string1 = JSON.stringify(params.docs[i]);
var str = ',';
var string2 = '"';
var string3 =str+string2+ '_deleted'+ string2+ ':' + "true" ;
var res = string1 + string3 ;
}
}
}
}
######################
[
"2018-01-23T09:44:23.568738362Z stdout:
{\"_id\":\"123\",
\"_rev\":\"1-7836\"},
\"_deleted\":true"]
Use map and Object.assign instead of generating a string
var output = params.docs.map( s => Object.assign( {}, {"_deleted" :true}, s ) );
You can then convert this to string using JSON.stringify( output );
Demo
var params = {
"docs": [{
"_id": "123",
"_rev": "1-7836",
},
{
"_id": "456",
"_rev": "1-1192",
}
]
};
var output = params.docs.map(s => Object.assign({}, {
"_deleted": true
}, s));
console.log(output);
var data = {
"docs": [
{
"_id": "123",
"_rev": "1-7836",
},
{
"_id": "456",
"_rev": "1-1192",
}
]
}
var newData = data['docs'].map(item => {
item._delete = true
return item
})
console.log(newData);
Why don't you simply put ._deleted attribute to doc, like this ?
function main(params) {
for (var i = 0; i< params.docs.length; i++) {
params.docs[i]._deleted = true;
var res = JSON.stringify(params.docs[i]);
}
}
}
Or like this :
function main(params) {
for (var i = 0; i< params.docs.length; i++) {
params.docs[i]["_deleted"] = true;
var res = JSON.stringify(params.docs[i]);
}
}
}
You can reference the not existing attribute directly and assign an value:
#!/usr/bin/js
var myJSON = { "docs": [ { "_id":"123", "_rev":"1-200" } ] }
console.log(myJSON);
myJSON.docs[0]["_deleted"]=true;
console.log(myJSON);
Output of example:
# js append.js
{ docs: [ { _id: '123', _rev: '1-200' } ] }
{ docs: [ { _id: '123', _rev: '1-200', _deleted: true } ] }
Read the more extensive example here: Add new attribute (element) to JSON object using JavaScript
So this might be a duplicate ...