Changing value after parsing from API - javascript

I'm parsing the following from:
json.listMap.forEach((listItem: { State: string; Country: string})```
Response.data looks like this:
```{
success: true,
listMap: [
{
State : 'Northrine Westfalia',
Country: 'Germany'
},
{
{
State : 'Bavaria',
Country: 'Germany'
}
}
]
}
How can I convert the value in country currently being 'Germany' to 'Deutschland' after parsing it from the API using Java Script?
-> Let me be more open here. I don't really know that method I could use to do this. Maybe someone could point me at a documentation, of course I don't expect anyone to just hand me the code.

Here's a general approach passing in the data, and from, and to arguments. It then uses map to return a new array of objects, changing the country where necessary.
Note: check your data for errors as you had some spare brackets in your example.
const data = {
success: true,
listMap: [{
State: 'Northrine Westfalia',
Country: 'Germany'
},
{
State: 'Bavaria',
Country: 'Germany'
}
]
}
function swap(data, prop, from, to) {
return data.listMap.map(obj => {
// Copy the object otherwise we'll return
// an array of objects that point
// to the old references
const newObj = {...obj};
if (newObj[prop] === from) newObj[prop] = to;
return newObj;
});
}
console.log(swap(data, 'Country', 'Germany', 'Deutchland'));
console.log(swap(data, 'State', 'Bavaria', 'New Bavaria'));

Use Array.map after parsing JSON into an JavaScript array:
const list = response.listMap.map(entry => {
return {
State : entry.State,
Country: entry.Country.replaceAll('Germany', 'Deutschland')
}
})
Of course, if you need JSON structure, just convert final array into JSON string with the following:
const newJSONList = JSON.stringify(list);

try this :
listMap = listMap.map(listMapItem => {
if ('Germany'===listMapItem.Country) {
listMapItem.Country = 'Deutschland';
return listMapItem;
} else {
return listMapItem;
}
});

assuming below is your response object.
var responsObj={ success: true,
listMap: [
{
State : 'Northrine Westfalia',
Country: 'Germany'
},
{
State : 'Bavaria',
Country: 'Germany'
}
]
};
responsObj.listMap=responsObj.listMap.map(x=>{
if(x.Country=="Germany"){
x.Country="Deutschland";
}
return x;
});
console.log(responsObj.listMap);

Something like this might help your requirement.
const rawJson = {
success: true,
listMap: [
{
State: 'Northrine Westfalia',
Country: 'Germany'
},
{
State: 'Bavaria',
Country: 'Germany'
}
]
};
for (itemObj of rawJson.listMap) {
// If needed, you can add check for current value to be 'Germany'
// if (itemObj.Country === 'Germany')
itemObj.Country = 'Deutschland';
}
console.log(rawJson);
Output:
{
success: true,
listMap: [
{ State: 'Northrine Westfalia', Country: 'Deutschland' },
{ State: 'Bavaria', Country: 'Deutschland' }
]
}

Related

Typescript/NestJS - extract object from db query response

I'm using external API to make an SQL query for a user. As a result i get matching Entity but as a set of fields, lookin like this:
[
{ IsNull: false, Name: 'Key', Value: '897', Values: null },
{ IsNull: false, Name: 'FirstName', Value: 'User', Values: null },
{ IsNull: false, Name: 'LastName', Value: 'Portal', Values: null },
{
IsNull: false,
Name: 'Email',
Value: 'some#email.com',
Values: null
},
{ IsNull: true, Name: 'Salutation', Value: null, Values: null },
{ IsNull: false, Name: 'Type', Value: '2', Values: null },
{
IsNull: false,
Name: 'LastLoggedDate',
Value: '2022-12-01 15:24:03',
Values: null
}
]
How to transform this response to end with simple object { email: 'some#email', firstName: 'User' lastName: 'Portal' } ??
I ended up with solution like this (below) but i believe there's some easiest way to do that, especially with more fields
let userRawEntity = queryResult.data.Entities[0].Fields;
const userEmail = userRawEntity.filter((obj) => { return obj.Name === 'Email' });
const userFirstName = userRawEntity.filter((obj) => { return obj.Name === 'FirstName' });
const userLastName = userRawEntity.filter((obj) => { return obj.Name === 'LastName' });
return { email: userEmail[0].Value, firstName: userFirstName[0].Value, lastName: userLastName[0].Value };
Edit:
final solution that works and looks nicer. thanks for help :)
if (queryResult.data.TotalEntityCount > 0) {
let user: {[key: string]: string | null } = {}
let userRawEntity = queryResult.data.Entities[0].Fields;
userRawEntity.forEach(data => user[data.Name] = data.Value);
return { email: user.Email, currency: user.Currency } as JwtPayload;
}
As a starting point, I would transform that entire array into an object as follows:
let dataTransformed: {[key: string]: string | null} = {}
data.forEach(d => {
dataTransformed[d.Name] = d.Value
})
Which will give you a nicer looking object as follows:
{
"Key": "897",
"FirstName": "User",
"LastName": "Portal",
"Email": "some#email.com",
"Salutation": null,
"Type": "2",
"LastLoggedDate": "2022-12-01 15:24:03"
}
You now have a familiar object with which to work with. From here, you can strip out the entries you don't want. Note, you may want to do further work in that array transformation such as checking for null values, changing keys to camel case, etc...
Another approach using lodash
_.mapValues(_.keyBy(data, "Name"), o => o.Value || o.Values);

Is there a way to transform a JavaScript object into another object with cleaner formatting?

When accessing a public register API, I receive more information than I need, and sometimes the data is returned with minor variations. I would like to delete some unnecessary fields, move nested fields to the top level, and rename them. The goal is to standardise format across several different APIs, and keep the memory requirement to a minimum. Example below:
Raw object:
[
{
startDate: "2022/08/27",
expiryDate: "2025/08/27",
party: {
type: "Business",
name: "Irregular Expressions Inc."
},
location: {
type: "Office",
address: {
locality: "Boston",
postcode: "PE21 8QR"
}
}
},
{
startDate: "2023/12/22",
expiryDate: "2024/06/22",
party: {
type: "Charity",
name: "Save the Badgers"
},
site: {
type: "Office",
address: {
locality: "Badgerton",
postcode: "BA6 6ER"
}
}
},
]
I want to transform this into a smaller, cleaner array:
[
{
startDate: "2022/08/27",
expiryDate: "2025/08/27",
partyName: "Irregular Expressions Inc.",
location: "Boston"
},
{
startDate: "2023/12/22",
expiryDate: "2024/06/22",
partyName: "Save the Badgers",
location: "Badgerton"
},
]
I have tried the below, but I'm getting an error.
module.exports = {
testTransform: (inputArray) => {
const outputArray = []
inputArray.forEach(element => {
outputArray.push({
startDate: element.startDate,
expiryDate: element.expiryDate,
partyName: element.party.name,
location: element.location.address.locality
})
})
return JSON.stringify(outputArray, null, ' ')
}
}
TypeError: Cannot read properties of undefined (reading 'address')
Am I going in the right direction, or is there a simpler way of doing this? I've searched for this type of transformation but with no luck - what am I missing?
You could take either location or site with logical OR || and later the proerties with optional chaining operator ?..
const
data = [{ startDate: "2022/08/27", expiryDate: "2025/08/27", party: { type: "Business", name: "Irregular Expressions Inc." }, location: { type: "Office", address: { locality: "Boston", postcode: "PE21 8QR" } } }, { startDate: "2023/12/22", expiryDate: "2024/06/22", party: { type: "Charity", name: "Save the Badgers" }, site: { type: "Office", address: { locality: "Badgerton", postcode: "BA6 6ER" } } }],
result = data.map(o => ({
startDate: o.startDate,
expiryDate: o.expiryDate,
partyName: o.party.name,
location: (o.location || o.site)?.address?.locality
}));
console.log(result);
Since it looks like you don't know what the outer key will be for the object with the address property, if the object will always have 4 properties, when destructuring, you can use rest syntax to collect the final property into a single object, and then take that object's values to get to the address.
const input=[{startDate:"2022/08/27",expiryDate:"2025/08/27",party:{type:"Business",name:"Irregular Expressions Inc."},location:{type:"Office",address:{locality:"Boston",postcode:"PE21 8QR"}}},{startDate:"2023/12/22",expiryDate:"2024/06/22",party:{type:"Charity",name:"Save the Badgers"},site:{type:"Office",address:{locality:"Badgerton",postcode:"BA6 6ER"}}}];
const output = input.map(({
startDate,
expiryDate,
party,
...rest
}) => ({
startDate,
expiryDate,
partyName: party.name,
location: Object.values(rest)[0].address.locality,
}));
console.log(output);
You are trying to read locality property of undefined. You could use optional chaining operator to prevent the exception throwing. So, you need to use somthing like element?.location?.address?.locality instead of element.location.address.locality.
That would require writing a function that recurcively goes throught the contents of an object an returns a non-nested object. The function below is such a function.
const flattenObject = (obj) => {
let result = {};
for (const i in obj) {
if ((typeof obj[i]) === 'object') {
const temp = flattenObject(obj[i]);
for (const j in temp) {
result[j] = temp[j];
}
}
else {
result[i] = obj[i];
}
}
return result;
};
The function can then be called on each nested object in the array. The map method of arrays would be do nicely for that step.
const result = nested.map(n => flattenObject(n))
console.table(result[0]) would produce the output below

Extracting values from array-attributes of a JSON array

I have an array of elements and each element is super-complex because its attributes are arrays which contains other arrays as properties. I want to extract just few attributes of this element, I've tried with the forEach function but it doesn't work.
The array comes from a json file, that's why I use axios, and the elements of the array are something like this:
{
"ITEMS":[
{
"id":"0001",
"name":"foo",
"sizes":[
{
"name":"small",
"id":"9999",
"available":"no"
},
{
"name":"medium",
"id":"9998",
"available":"yes"
}
]
},
{
"id":"0002",
"name":"bar",
"sizes":[
{
"name":"small",
"id":"4444",
"available":"yes"
},
{
"name":"medium",
"id":"4443",
"available":"no"
}
]
},
...
]
}
So I want to collect the their attributes creating elements that are PUSHED in an array and that replicate this model:
this.sample = {
colour:'item.name',
size:'item.size.name[i]',
idcode:'item.id',
sizecode:'item.size.id[i]',
available:'item.size.available[i]'
}
this is my attempt (not working)
const axios = require('axios');
class IndianaJones {
constructor(){
this.sample = {
name:'',
colour:'',
size:'',
idcode:'',
sizecode:'',
available:''
},
this.newids = ["10","11","12"...]
this.freshprods = []
}
async FreshProd(){
for(this.i=0;this.i<this.newids.length;this.i++){
this.prod = await axios.get(`https://blablabla/${this.newids[this.i]}.json`)
this.ITEMS.forEach(function(item){
this.sample.idcode=item.id;
this.sample.colour=item.name;
item.sizes.forEach(function(SIZE){
this.sample.size=SIZE.name
this.sample.sizecode=SIZE.id
this.sample.available=SIZE.available
this.freshprods.push(this.sample)
})
}
)
}
return this.freshprods
}
}
(async()=>{
const indiana = new IndianaJones();
await indiana.FreshProd()
})()
Really, this is driving me up to wall, i would be SO GRATEFUL for anyone who can help me, maybe LODASH could be useful?
You are trying to flatten the structure. To so you can use Array.flatMap() (or lodash's _.flatMap() to iterate the ITEMS, map the sizes array, and return a new object for each size:
const prods = {"ITEMS":[{"id":"0001","name":"foo","sizes":[{"name":"small","id":"9999","available":"no"},{"name":"medium","id":"9998","available":"yes"}]},{"id":"0002","name":"bar","sizes":[{"name":"small","id":"4444","available":"yes"},{"name":"medium","id":"4443","available":"no"}]}]};
const freshprods = prods.ITEMS.flatMap(
({ id: idcode, name: colour, sizes }) =>
sizes.map(o => ({
colour,
size: o.name,
idcode,
sizecode: o.id,
available: o.available
}))
);
console.log(freshprods);
let prod = {
"ITEMS":[
{
"id":"0001",
"name":"foo",
"sizes":[
{
"name":"small",
"id":"9999",
"available":"no"
},
{
"name":"medium",
"id":"9998",
"available":"yes"
}
]
},
{
"id":"0002",
"name":"bar",
"sizes":[
{
"name":"small",
"id":"4444",
"available":"yes"
},
{
"name":"medium",
"id":"4443",
"available":"no"
}
]
}
]
}
let freshprods = [];
prod.ITEMS.forEach(function(item){
item.sizes.forEach(function(SIZE){
freshprods.push({
idcode: item.id,
colour: item.name,
size: SIZE.name,
sizecode: SIZE.id,
available: SIZE.available
})
})
})
console.log(freshprods);
Output
[ { idcode: '0001',
colour: 'foo',
size: 'small',
sizecode: '9999',
available: 'no' },
{ idcode: '0001',
colour: 'foo',
size: 'medium',
sizecode: '9998',
available: 'yes' },
{ idcode: '0002',
colour: 'bar',
size: 'small',
sizecode: '4444',
available: 'yes' },
{ idcode: '0002',
colour: 'bar',
size: 'medium',
sizecode: '4443',
available: 'no' } ]

GraphQL object property should be a list of strings

How do I make a schema for an object property that is an array of strings in GraphQL? I want the response to look like this:
{
name: "colors",
keys: ["red", "blue"]
}
Here is my Schema
var keysType = new graphql.GraphQLObjectType({
name: 'keys',
fields: function() {
key: { type: graphql.GraphQLString }
}
});
var ColorType = new graphql.GraphQLObjectType({
name: 'colors',
fields: function() {
return {
name: { type: graphql.GraphQLString },
keys: { type: new graphql.GraphQLList(keysType)
};
}
});
When I run this query I get an error and no data, the error is just [{}]
query { colors { name, keys } }
However when I run a query to return just the name I get a successful response.
query { colors { name } }
How do I create a schema that returns an array of strings for when I query for keys?
I figured out the answer. The key is to pass the graphql.GraphQLString into graphql.GraphQLList()
The schema becomes:
var ColorType = new graphql.GraphQLObjectType({
name: 'colors',
fields: function() {
return {
name: { type: graphql.GraphQLString },
keys: { type: new graphql.GraphQLList(graphql.GraphQLString)
};
}
});
Using this query:
query { colors { name, keys } }
I get the desired results:
{
name: "colors",
keys: ["red", "blue"]
}

Recursive Function Causing Overflow

I am trying to write a recursive function in JavaScript. My function needs to search a tree of items. I have created a JSFiddle. When I run the JavaScript in Chrome, I get an error that says:
RangeError: Maximum call stack size exceeded
I assume this means that I'm not returning my value at the correct time. However, I continue to review the function and it looks correct to me. What am I doing wrong?
var sitemap = [
{
name: 'dashboards', children: [
{ name: 'dashboard 1', route: '/dashboards/dashboard1', html: '' }
]
},
{
name: 'objects', children: [
{ name: 'players', route: '/objects/players', html: '/objects/players.html' },
{ name: 'teams', route: '/objects/teams', html: '/objects/teams.html' },
{ name: 'coaches', route: '/objects/coaches', html: '/objects/coaches.html' },
{ name: 'cities', children: [
{ name: 'Chicago', route: '/cities/chicago',
html: '/objects/cities/chicago.html' },
{ name: 'Philadelphia', route: '/cities/philadelphia', html: '/objects/cities/philadelphia.html' }
]},
]
}
];
var getFromSitemap = function (path, entries) {
var sitemapItem = null;
if (entries) {
angular.forEach(sitemap, function (entry, key) {
if (entry.hasOwnProperty("children")) {
sitemapItem = getFromSitemap(path, entry.children);
} else if (entry.route === path) {
sitemapItem = entry;
}
});
}
return sitemapItem;
};
var getItem = function() {
var item = getFromSitemap('/cities/chicago', sitemap);
console.log(item);
}
Thank you!
You are calling foreach on the same object (sitemap) everytime:
angular.forEach(sitemap, function ...
It seems like you want to be calling it on entries recursively
angular.forEach(entries, function ....

Categories