change value of an array of nested objects to a string - javascript

this is the array that i currently have
const myArr = [
{
"code": {
"value": "AC16",
"description": "text"
},
"convictionDate": {
"value": "2019-03-07"
}
},
{
"code": {
"value": "AC20",
"description": "text"
},
"convictionDate": {
"value": "2019-03-06"
}
}
];
I want to map over each nested object inside the array so that the value of each nested object is the value property of that object as a string. so the object would become:
const myArr = [
{
"code": "AC16",
"convictionDate":"2019-03-07"
},
{
"code":"AC20",
"convictionDate": "2019-03-06"
}
]
Ive tried this with no success:
const x = myArr.map((item)=>{
console.log(item)
Object.keys(item).map(function(key,i) {
item[key] = item[key][value];
})
})

You are almost there. Just use array map
const myArr = [{
"code": {
"value": "AC16",
"description": "text"
},
"convictionDate": {
"value": "2019-03-07"
}
},
{
"code": {
"value": "AC20",
"description": "text"
},
"convictionDate": {
"value": "2019-03-06"
}
}
];
let newArray = myArr.map(function(item) {
return {
code: item.code.value,
convictionDate: item.convictionDate.value
}
});
console.log(newArray)

Map the array, and reduce the entries to the required object form:
const myArr = [{"code":{"value":"AC16","description":"text"},"convictionDate":{"value":"2019-03-07"}},{"code":{"value":"AC20","description":"text"},"convictionDate":{"value":"2019-03-06"}}];
const result = myArr.map(o =>
Object.entries(o).reduce((r, [k, { value }]) => ({ ...r, [k]: value }), {})
);
console.log(result);

const myArr = [
{
"code": {
"value": "AC16",
"description": "text"
},
"convictionDate": {
"value": "2019-03-07"
}
},
{
"code": {
"value": "AC20",
"description": "text"
},
"convictionDate": {
"value": "2019-03-06"
}
}
];
let newArray = myArr.map(e => {
return { "code":e.code.value, "convictionDate": e.convictionDate.value}
})
console.log(newArray);

It goes without saying there is some awesome reference material over at W3 Schools, the provide good detail on this in their article here
That said...
Why not simplify the code a little and try this against your array:-
const myArr = [
{
"code": {
"value": "AC16",
"description": "text"
},
"convictionDate": {
"value": "2019-03-07"
}
},
{
"code": {
"value": "AC20",
"description": "text"
},
"convictionDate": {
"value": "2019-03-06"
}
}
];
// PROPOSED SOLUTION CODE
const x = myArr.map((item)=>{
return {code: item.code.value,convictionDate: item.convictionDate.value}
});
// Your Desired Example Provided in Question
const xArr = [
{
"code": "AC16",
"convictionDate":"2019-03-07"
},
{
"code":"AC20",
"convictionDate": "2019-03-06"
}
];
// Output Validation
console.log('Response of Array \'x\'');
console.log(x);
console.log('Your Desired Example');
console.log(xArr);
When using 'map'; we must map the source array ('myArr') to our new target array ('x').
In the context of the example code you have provided, 'data.convictions' is undefined.
The magic is all here:-
const x = myArr.map((item)=>{
return {code: item.code.value,convictionDate: item.convictionDate.value}
});
Happy coding!

Related

How to combine multiple JSON object that have same key and value

How to combine JSON objects in the same response that has the same key and value with javascript? This is my data for example:
{
"data": [
{
"name": "A",
"description": {
"location": "location1",
"floor": "floor1",
},
},
{
"name": "A",
"description": {
"location": "location2",
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
}
And turn it into this:
{
"data": [
{
"name": "A",
"description": {
"location": ["location1","location2"],
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
}
Basically I am someone who is new to learning javascript. Any help would be very helpful, thank you.
You can do:
const data = {data: [{name: 'A',description: {location: 'location1',floor: 'floor1',},},{name: 'A',description: {location: 'location2',floor: 'floor1',},},{name: 'B',description: {location: 'location3',floor: 'floor3',},},],}
const result = {
data: data.data.reduce((a, { name, description }) => {
const index = a.findIndex((d) => d.name === name)
if (index >= 0) {
let location = a[index].description.location
location = Array.isArray(location) ? location : [location]
a[index].description.location = [...location, description.location]
} else {
a.push({ name, description })
}
return a
}, []),
}
console.log(result)
const list = {
"data": [
{
"name": "A",
"description": {
"location": "location1",
"floor": "floor1",
},
},
{
"name": "A",
"description": {
"location": "location2",
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
};
const consolidatedData = [];
for (const ele of list.data) {
const isExist = consolidatedData.find(x => x.name === ele.name);
if (!isExist) {
consolidatedData.push({
...ele
})
} else {
const objectKey = consolidatedData.findIndex(x => x.name === ele.name);
if (objectKey > -1) {
const description = consolidatedData[objectKey].description;
const newDes = ele.description;
if (newDes.location !== description.location) {
const data = consolidatedData[objectKey].description;
const added = [data.location, ele.description.location];
delete consolidatedData[objectKey].description.location
consolidatedData[objectKey].description["location"] = added
}
if (newDes.floor !== description.floor){
const data = consolidatedData[objectKey].floor;
const added = [data.floor, ele.description.floor];
delete consolidatedData[objectKey].description.floor
consolidatedData[objectKey].description["floor"] = added
}
}
}
}
console.log(JSON.stringify(consolidatedData, null, 2));
Here is a solution that uses an intermediate bucket object. The desired result object is then constructed from the bucket object:
const input = { "data": [ { "name": "A", "description": { "location": "location1", "floor": "floor1", }, }, { "name": "A", "description": { "location": "location2", "floor": "floor1", }, }, { "name": "B", "description": { "location": "location3", "floor": "floor3", }, }, ] };
let buckets = input.data.reduce((acc, obj) => {
if(!acc[obj.name]) {
acc[obj.name] = {
locations: {},
floors: {}
};
}
acc[obj.name].locations[obj.description.location] = true;
acc[obj.name].floors[obj.description.floor] = true;
return acc;
}, {});
console.log('buckets: ', buckets);
let result = {
data: Object.keys(buckets).map(name => {
let locations = Object.keys(buckets[name].locations);
let floors = Object.keys(buckets[name].floors);
return {
name: name,
description: {
location: locations.length == 1 ? locations[0] : locations,
floor: floors.length == 1 ? floors[0] : floors
}
}
})
};
console.log('result:', result);
Notes:
buckets object:
is created using an array .reduce()
array .reduce() docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
locations and floors are collected using objects instead of arrays, this is to avoid duplicate names
result object:
is using Object.keys(buckets) to get the array of names
.map() transforms each name into the desired object
your unusual array or string value for location and floor is constructed with a conditional

Put JSON data inside another object of the same JSON

I need to put the images that are on "included" into "data:{relationships: { field_imagen: { data" but the problem is that i just managed to put only the first image into every index using map and find
noticiasImages.forEach(function(data: { relationships: { field_imagen: {data: {id:any}}}} ) {
var nestedArray = noticiasData.map((noticiasImages: { id: any; }) => noticiasImages == noticiasData);
data = nestedArray && noticiasImages || noticiasData;
});
And this is my json (example node)
{
"data": [
"relationships": {
"field_imagen": {
"data": [
{
"type": "file--file",
"id": "dba917f0-b80f-45ed-a569-69f2ba2b482d",
}
],
}
]
},
this is the included object, who is in the same level as data
"included": [
"attributes": {
"drupal_internal__fid": 8798,
"langcode": "es",
"filename": "_DSC6472 - copia.jpg",
"uri": {
"value": "public:\/\/2019-11\/_DSC6472 - copia.jpg",
"url": "\/sites\/default\/files\/2019-11\/_DSC6472%20-%20copia.jpg"
},
},
,
Expected Result:
"data": [
"relationships": {
"type": "node--actualidad_institucional",
"id": "71514647-af49-4136-8a28-9563d133070a",
"field_imagen": {
"data": [
{
"type": "file--file",
"id": "dba917f0-b80f-45ed-a569-69f2ba2b482d",
"uri": {
"value": "public:\/\/2019-11\/_DSC6472 - copia.jpg",
"url": "\/sites\/default\/files\/2019-11\/_DSC6472%20-%20copia.jpg"
},
}
}
},
I put the uri from included into field_imagen. Tried to resolve like that, but it just put only the first image of the Array from the included object in every node:
showNoticias() {
this.frontService.getNoticias()
.subscribe((data: Noticias) => {
this.noticiasImages = Array.from(data.included);
this.noticiasData = Array.from(data.data);
let noticiasImages = this.noticiasImages.map((data: {id: any}) => data.id);
let noticiasData = this.noticiasData.map((data:{relationships: { field_imagen: { data: { id: any; }}}}) => data.relationships.field_imagen.data.id);
noticiasImages.forEach(function(data: { relationships: { field_imagen: {data: {id:any}}}} ) {
var nestedArray = noticiasData.map((noticiasImages: { id: any; }) => noticiasImages == noticiasData);
data = nestedArray && noticiasImages || noticiasData;
});
console.log(data);
});
}
Hope you can help me, thanks!
UPDATE: tried that but didnt work like expected
let merged = data.data.map((data:{relationships: { field_imagen: { data: any }}}) => Object.assign({}, noticiasImages));
console.log(data)
console.log(merged)
Sometimes using regular for loops are a better option. Using map with objects that have that many properties can get confusing. And using forEach will not give you access to the i index of the iteration in the loop, which makes things easier in this case.
for (let i = 0; i < obj.included.length; i++) {
let uri = obj.included[i].attributes.uri;
obj.data[i].relationships.field_imagen.data[0] = {
...obj.data[i].relationships.field_imagen.data[0],
...uri
}
}
console.log(obj)
Output:
{
"data": [
{
"relationships": {
"field_imagen": {
"data": [
{
"type": "file--file",
"id": "dba917f0-b80f-45ed-a569-69f2ba2b482d",
"value": "public://2019-11/_DSC6472 - copia.jpg",
"url": "/sites/default/files/2019-11/_DSC6472%20-%20copia.jpg"
}
]
}
}
}
],
"included": [
{
"attributes": {
"drupal_internal__fid": 8798,
"langcode": "es",
"filename": "_DSC6472 - copia.jpg",
"uri": {
"value": "public://2019-11/_DSC6472 - copia.jpg",
"url": "/sites/default/files/2019-11/_DSC6472%20-%20copia.jpg"
}
}
}
]
}

How grab key from api call in this js example

So in the API response example below, focusing on env_variables, I am trying grab the value for secret. I am stuck because as you can see, the name and value are not nested together. I am not familiar with how to grab the value based on the name in this example.
api response:
{
"id": 1146,
"job": {
"name": "jobname1",
},
"env_variables": [
{
"name": {
"name": "test1"
},
"value": {
"value": "10.13.6"
}
},
{
"name": {
"name": "test1"
},
"value": {
"value": "10.13.6"
}
},
],
},
{
"id": 1147,
"job": {
"name": "jobname2",
},
"env_variables": [
{
"name": {
"name": "secret"
},
"value": {
"value": "10.13.7"
}
},
{
"name": {
"name": "test5"
},
"value": {
"value": "10.13.6"
}
},
],
}
js
jobs: []
apiEndpoint = "test.com/api"
fetch(this.apiEndpoint)
.then(response => response.json())
.then(body => {
for(let i=0; i<body.length; i++){
this.jobs.push({
'build_id': JSON.stringify(body[i].id),
'secret': //not sure how to pull the value (10.13.7)
})
}
})
You need nested loops, since there are two nested arrays: the top level of the response is an array of objects, and env_variables contains an array of objects.
fetch(this.apiEndpoint)
.then(response => response.json())
.then(body => {
for (let i = 0; i < body.length; i++) {
let env = body[i].env_variables;
for (let j = 0; j < env.length; j++) {
if (env[j].name.name == "secret") {
this.jobs.push({
'build_id': JSON.stringify(body[i].id),
'secret': env[j].value.value
})
}
}
}
})
You can do something like this inside .then(body=>...
const body = [{ //it looks like brackets [] were lost in OP
"id": 1146,
"job": {
"name": "jobname1",
},
"env_variables": [{
"name": {
"name": "test1"
},
"value": {
"value": "10.13.6"
}
},
{
"name": {
"name": "test1"
},
"value": {
"value": "10.13.6"
}
},
],
},
{
"id": 1147,
"job": {
"name": "jobname2",
},
"env_variables": [{
"name": {
"name": "secret"
},
"value": {
"value": "10.13.7"
}
},
{
"name": {
"name": "test5"
},
"value": {
"value": "10.13.6"
}
},
],
}
];
let secret = null;
body.forEach(b => {
let el = b.env_variables.find(e => e.name.name == 'secret');
if (el) { //found
secret = el.value.value;
return false; //exit forEach
}
});
console.log(secret);
You could also do something like this with Array.forEach and Array.find:
let data = [{ "id": 1146, "job": { "name": "jobname1", }, "env_variables": [{ "name": { "name": "test1" }, "value": { "value": "10.13.6" } }, { "name": { "name": "test1" }, "value": { "value": "10.13.6" } }, ], }, { "id": 1147, "job": { "name": "jobname2", }, "env_variables": [{ "name": { "name": "secret" }, "value": { "value": "10.13.7" } }, { "name": { "name": "test5" }, "value": { "value": "10.13.6" } }, ], } ]
let jobs = []
data.forEach(({id, env_variables}) => jobs.push({
build_id: id,
secret: ((env_variables.find(({name}) =>
name.name === 'secret') || {}).value || {}).value || 'N/A'
// ... other props
}))
console.log(jobs)
Assuming your result is an array, you could do something like this:
let secrets = results.reduce((result, item) => {
let secret = item["env_variables"].find((v) => {return v.name.name === "secret"})
if(secret){
result.push({id:item.id, secret: secret.value.value});
}
return result;
}, []);
This would return an array of objects like {id: 1, secret: ""} for each object in your result set that has a secret.
If you don't care whether the secret is present or not, you could modify the code slightly like this:
let secrets = results.reduce((result, item) => {
let secret = item["env_variables"].find((v) => {return v.name.name === "secret"})
result.push({id:item.id, secret: secret ? secret.value.value : ""});
return result;
}, []);
Which just leaves with you an empty string on the levels where there is no secret.

Reformat Existing JSON into new JSON using Javascript/Typescript

I currently have an existing JSON that I want to change/reformat into a new JSON to be able to be used in an external service. The format is a bit complicated but I can't change it, so I have to edit my existing JSON. to match my desired output.
Existing JSON:
{
"specifiers": [{
"value": "test",
"type": "text",
"label": "Brand ID"
}, {
"value": "test",
"type": "text",
"label": "Program ID"
}]
}
Desired Output:
{
"specifiers": {
"Brand ID": {
"text": {
"value": "test",
"type": "text"
}
},
"Program ID": {
"text": {
"value": "test",
"type": "text"
}
}
}
}
I've tried iterating through the existing JSON using loops, but I don't really know how to format my loops to use the values as the keys? I'm guessing that I might have to use Object.keys or Object.values, but I'm not sure how to get a specific value for a specific key.
Example Format:
"[label]": {
"[type]": {
"value": [value],
"type": [type]
}
}
function tranform({specifiers}) {
return { specifiers: specifiers.reduce((obj, {label, type, value}) => ({...obj, [label]: { [type]: { type, value } } }), {}) }
}
const json = {
"specifiers": [{
"value": "test",
"type": "text",
"label": "Brand ID"
}, {
"value": "test",
"type": "text",
"label": "Program ID"
}]
}
console.log(tranform(json))
Pretty straightforward with a reduce:
const formattedSpecifiers = existingJSON.specifiers.reduce((newSpecifiers, specifier) => {
newSpecifiers[specifier.label] = {
[specifier.type]: {
type: specifier.type,
value: specifier.value,
},
};
};
return newSpecifiers;
}, {});
const newJSON = { specifiers: formattedSpecifiers };
you can use #Array.reduce. snippet below.
let input = {
"specifiers": [{
"value": "test",
"type": "text",
"label": "Brand ID"
}, {
"value": "test",
"type": "text",
"label": "Program ID"
}]
}
const res = input.specifiers.reduce((res, obj) => {
const {
label,
type,
value
} = obj
res[label] = {};
res[label][type] = {
value,
type
};
return res;
}, {});
console.log(res);

node js create an object in specific pattern from array of object

I'm facing some issue in for loop while creating an object from array of object.I have an array as this in node js app:
[
{
"Material": "113/133",
"Name": [
{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [
{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
]
I want to return object like this which contains all the Material as array, Name and there value in array of object like this:
{
Material: ["113/133", "150/300"],
datasets: [
{
label: "WELD1",
data: [27520,1441]
},
{
label: "WELD2",
data: [676992,555]
},
{
label: "WELD3",
data: [100,20,0]
}
]
}
I want to get result using for loop.
you can use .reduce() and do something like this:
var arr = [
{
"Material": "113/133",
"Name": [
{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [
{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
];
var newArr = arr.reduce((acc, ob) => {
for (var key in ob)
if(typeof acc[key] === 'object')
acc[key] = acc[key] ? acc[key].concat(ob[key]) : [ob[key]];
else
acc[key] ? acc[key].push(ob[key]) : acc[key] = [ob[key]];
return acc;
}, {});
console.log(newArr);
let array = [
{
"Material": "113/133",
"Name": [
{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [
{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
]
let answer = {Material: [], datasets: []}
array.forEach(x => {
answer.Material.push(x.Material);
x.Name.forEach(na => {
let object = answer.datasets.find(obj => obj.label === na.name) || {label: "", data: []};
if(object.label === ""){
object.label = na.name;
object.data.push(na.value);
answer.datasets.push(object);
}else{
object.data.push(na.value)
}
});
});
console.log(answer);
The above is alternative solution using forEach instead of reduce
Use of Array.reduce to build your new data structure using data you have
const start = [{
"Material": "113/133",
"Name": [{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
];
const end = start.reduce((tmp, {
Material,
Name,
}) => {
// Handle the material
// If it do not exist in the array, push it
if (!tmp.Material.includes(Material)) {
tmp.Material.push(Material);
}
// Handle the datasets
// Look at each Name
Name.forEach(({
name,
value,
}) => {
// Can we find the label?
const labelFind = tmp.datasets.find(y => y.label === name);
// If we can't find the label, create a new dataset
if (!labelFind) {
tmp.datasets.push({
label: name,
data: [
value,
],
});
return;
}
// If we has found it push new value in the dataset
labelFind.data.push(value);
});
return tmp;
}, {
Material: [],
datasets: [],
});
console.log(end);
// This is the old fashioned way.
// Iterate over whole array,
// make a map, push value where 'name' is found in map
// later iterate over this map - dataMap - and form required datasets array.
var Material = [];
var dataMap = {};
arr.forEach(obj => {
Material.push(obj.Material);
obj.Name.forEach(item => {
if(dataMap[item.name]){
dataMap[item.name].push(item.value);
}
else {
dataMap[item.name] = [item.value];
}
});
});
var datasets = [];
Object.keys(dataMap).forEach(label => {
datasets.push({
label: label,
data: dataMap[label]
});
});
var result = {
Material: Material,
datasets: datasets
}
console.log(result);

Categories