AWS GraphQL JSON string formatting - arrays

I'm attempting to create an object value to pass into DynamoDB using AWS AppSync and GraphQL. I'm very close to what I need but I'm stumbling on nested JSON.
Let's say I have an array:
let officers = [{"id":"0","IgRole":"Role1","IgName":"testname1","IgEmail":"testemail1","IgPhone":"testphone1","IgStart":"teststart1","IgEnd":"testend1"},
{"id":"1","IgRole":"Role2","IgName":"testname2","IgEmail":"testemail2","IgPhone":"testphone2","IgStart":"teststart2","IgEnd":"testend2"}]
I now want to create an object with each of the array values as a child object so, I do this:
for (let i in officers) {
officersJson['"' + officers[i].IgRole + '"'] = '{"Name":"' + officers[i].IgName + '","Email":"' + officers[i].IgEmail + '","Phone":"' + officers[i].IgPhone + '","Date commenced":"' + officers[i].IgStart + '","Date to end":"' + officers[i].IgEnd + '"}';
}
Here are the results:
Object {
"Role1": "{'Name':'testname1','Email':'testemail1','Phone':'testphone1','Date commenced':'teststart1','Date to end':'testend1'}",
"Role2": "{'Name':'testname2','Email':'testemail2','Phone':'testphone2','Date commenced':'teststart2','Date to end':'testend2'}"
}
I think the problem is that the each entire key / value is not in string format. If you look at
"Role1": "{......
you can see that the string breaks.
and this is the response from AWS:
Variable 'Officers' has an invalid value. Unable to parse {\"Role1\"={\"Nam
See the = sign
How can I format the object into a complete JSON string? I was fairly pleased I managed to get anywhere near the format I needed but this last bit has me stumped.

Finally worked it out. I needed a slightly different approach. Posting it in case it helps anyone else:
Firstly I created an array of roles, as this will be the keys for the value objects:
for (let i in officers) {
roles.push(officers[i].IgRole);
}
I then created a new array.
let arrOfficers = [];
for (let i in officers) {
arrOfficers.push(officers[i]);
}
I then use a function to create objects from an array:
function groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
let key = obj[property];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
}
let newresult = groupBy(arrOfficers, "IgRole");
Finally I create my object and then stringify it:
let officersJson = {};
for (let i in roles) {
officersJson[roles[i]] = newresult[roles[i]][0];
}
theObjectIwant = JSON.stringify(officersJson)

Related

Fetch Data from nested props in ReactJS

I am uploading the data from excel file using react-excel-renderer, storing the excel render response containing column & rows response in state and passing to other component.
Expected Use-case result:- I am fetching the data from excel using render storing the values in states(rows). I am passing the state to other component where i need these values to pass in API .
The data stored is in nested form. Can you please let me know how to get data separately stored under array in props. Attached is the screenshot.
Excel Render code:-
changeHandler(event) {
let fileObj = event.target.files[0];
//just pass the fileObj as parameter
ExcelRenderer(fileObj, (err, resp) => {
if (err) {
console.log(err);
} else {
this.setState({
cols: resp.cols,
rows: resp.rows,
});
}
});
}
Code to fetch the prop data:-
for (let i = 0; i < this.props.data.length; i++) {
let stDate = this.props.data[i].startDate;let TripName = this.props.data[i].TripName;
let totalFare = this.props.data[i].totalFare;
let FirstName = this.props.data[i].FirstName;
let LastName = this.props.data[i].LastName;
let Currency = this.props.data[i].Currency;
}
You can use an Array method
Still not 100% sure what your final data should look like, but it feels like you're using 2 arrays. 1 as the key and 1 as the value.
So to combine these 2 we can use Reduce
const keys = data[0];
const values = data[1];
keys.reduce((acc, keys, index) => {
return {...acc, [key]: values[index]}
}, {})
That will return an object of key values.

merge array of objects from fetched API with pagination with Google Apps Script

I'm fetching a URL. The full response is spread over five pages.
I'm looping through each pages which returns me an array of object (please correct me if I'm wrong):
[{item_1=foo, item_2=bar, item_3=foobar, value_1=XX}, {item_1=bar, item_2=foo, item_3=barfoo, value_1=XX},etc...]
I want to consolidate all the response like if it was one big array of objects.
So far, I wrote this:
for (i = 1; i <= total_pages; i++) {
var rawResponse = UrlFetchApp.fetch(
'url',
{
method: 'GET'
})
response[i] = JSON.parse(rawResponse);
}
var g = response[1].concat(response[2], response[3],response[4],response[5]);
g contains the desired output; however, as you can see, this is not dynamic. How can I solve this? I could you the push method, but I would return me a new array with each response.
In order to make your code "dynamic" you could use the concat function inside the for-loop, for each of the pages. A possible modification of your code could look like the following, where the result variable would contain all the results:
var result = [];
for (var i = 1; i <= total_pages; i++) {
var rawResponse = UrlFetchApp.fetch(
'url',
{
method: 'GET'
}
);
var current = JSON.parse(rawResponse);
result = result.concat(current);
}

Can't delete multiple images inside React Firebase Promises

I am basically trying to delete specific Firebase data in both my storage and my database according to values I have stored in an array. I have an array of objects that cointains a key (which is a child key used for both FirebaseStorage and FirebaseDatabase, a picture name and a file destination. To make sure that I don't just remove the reference to the picture, I also want to delete it in Firebase Storage. Therefore, I thought that the use of a for-loop would solve the problem. This is my code so far:
var key, count = 0;
for (key in delArray) {
if (delArray.hasOwnProperty(key)) {
count++;
}
}
for (index = 0; index < count && canProceed; index++) {
canProceed = false;
var deletionFileLocation = storageNews.child(newsId + "/" + delArray[index].key + "/" + delArray[index].name);
deletionFileLocation.delete().then(() => {
databaseNews.child(newsId).child('thumbnails').child(delArray[index].key).remove().then(() => {
canProceed = true;
});
});
if (index == delArray.length) {
console.log('done');
}
}
The strange thing with this code, is that it removes all(I think, as far as I have noticed) pictures, but only reference in the database. In other words, it only removes one child in the DB. What am I doing wrong here? Do I need to use callbacks with async await? If so, how would I approach it? I am fairly new to React, and I can't seem to understand how I would do it.
It looks like you have it arranged so that the for loop hangs the process until any one of the remove() promises resolves. The missing concept is Promise.all().
// moved to a promise-returning function so we can see what's going on
function deleteDataAndStorage(newsId, obj) {
let path = newsId + "/" + obj.key + "/" + obj.name;
let deletionFileLocation = storageNews.child(path);
return deletionFileLocation.delete().then(() => {
return databaseNews.child(newsId).child('thumbnails').child(obj.key).remove();
});
}
Now the loop is simple and clear. Promise.all() does what the name says: it resolves with an array of results when all of the promises you pass it have resolved.
let promises = [];
for (index = 0; index < count; index++) {
promises.push(deleteDataAndStorage(newsId, delArray[index]));
}
return Promise.all(promises).then(result => {
console.log('done');
});

Recover data from within children with Angularjs

can anybody help me? I'm having a problem similar to the previous post. I'm just not getting the child object. I have tried in several ways the most basic and logical would be: newPost.musician.statusbatera
Follows a chrome debug print: --Screen Shot--
I'm not getting it because of the key generated automatically by firebase as the print in attached.
My code:
var db = firebase.database();
var ref = db.ref("users");
ref.on("child_added", function(snapshot) {
var newPost = snapshot.val();
console.log("Musician: " + newPost.musician.statusbatera);
});
You can grab the autogenerated key using Object.keys, then you can assign the object you need:
ref.on("child_added", function(snapshot) {
var newPost = snapshot.val();
keys = Object.keys(newPost.musician)
console.log("Musician: " + newPost.musician[keys[0]].statusbatera);
});
in theory, there should be only one value in keys...
I think you want to iterate through musician's list, if so, give this a try :-
for(var i = 0; i <= newPost.musician.lenght; i++) {
console.log("Musician: " + newPost.musician[i].statusbatera);
}

GET with query string with Fetch in React Native

I am making a request like this:
fetch("https://api.parse.com/1/users", {
method: "GET",
headers: headers,
body: body
})
How do I pass query string parameters? Do I simply add them to the URL? I couldn't find an example in the docs.
Your first thought was right: just add them to the URL.
Remember you can use template strings (backticks) to simplify putting variables into the query.
const data = {foo:1, bar:2};
fetch(`https://api.parse.com/1/users?foo=${encodeURIComponent(data.foo)}&bar=${encodeURIComponent(data.bar)}`, {
method: "GET",
headers: headers,
})
Short answer
Just substitute values into the URL like this:
const encodedValue = encodeURIComponent(someVariable);
fetch(`https://example.com/foo?bar=${encodedValue}`);
Longer answer
Yes, you just need to add the query string to the URL yourself. You should take care to escape your query string parameters, though - don't just construct a URL like
`https://example.com/foo?bar=${someVariable}`
unless you're confident that someVariable definitely doesn't contain any &, =, or other special characters.
If you were using fetch outside of React Native, you'd have the option of encoding query string parameters using URLSearchParams. However, React Native does not support URLSearchParams. Instead, use encodeURIComponent.
For example:
const encodedValue = encodeURIComponent(someVariable);
fetch(`https://example.com/foo?bar=${encodedValue}`);
If you want to serialise an object of keys and values into a query string, you could make a utility function to do that:
function objToQueryString(obj) {
const keyValuePairs = [];
for (const key in obj) {
keyValuePairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
}
return keyValuePairs.join('&');
}
... and use it like this:
const queryString = objToQueryString({
key1: 'somevalue',
key2: someVariable,
});
fetch(`https://example.com/foo?${queryString}`);
Here's an es6 approach
const getQueryString = (queries) => {
return Object.keys(queries).reduce((result, key) => {
return [...result, `${encodeURIComponent(key)}=${encodeURIComponent(queries[key])}`]
}, []).join('&');
};
Here we're taking in a queries object in the shape of key: param
We iterate and reduce through the keys of this object, building an array of encoded query strings.
Lastly we do a join and return this attachable query string.
I did a small riff on Mark Amery's answer that will pass Airbnb's eslint definitions since many teams seem to have that requirement these days.
function objToQueryString(obj) {
const keyValuePairs = [];
for (let i = 0; i < Object.keys(obj).length; i += 1) {
keyValuePairs.push(`${encodeURIComponent(Object.keys(obj)[i])}=${encodeURIComponent(Object.values(obj)[i])}`);
}
return keyValuePairs.join('&');
}
My simple function to handle this:
/**
* Get query string
*
* #param {*} query query object (any object that Object.entries() can handle)
* #returns {string} query string
*/
function querystring(query = {}) {
// get array of key value pairs ([[k1, v1], [k2, v2]])
const qs = Object.entries(query)
// filter pairs with undefined value
.filter(pair => pair[1] !== undefined)
// encode keys and values, remove the value if it is null, but leave the key
.map(pair => pair.filter(i => i !== null).map(encodeURIComponent).join('='))
.join('&');
return qs && '?' + qs;
}
querystring({one: '##$code', two: undefined, three: null, four: 100, 'fi###ve': 'text'});
// "?one=%23%40%24code&three&four=100&fi%23%23%40ve=text"
querystring({});
// ""
querystring('one')
// "?0=o&1=n&2=e"
querystring(['one', 2, null, undefined]);
// "?0=one&1=2&2" (edited)
Yes you should, there are a few classes in JS, that can help you a handy one is https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
e.g. if you had the params in a javascript object say
let params = {one: 'one', two: 'two'}
you could say this function
let queryString = new URLSearchParams()
for(let key in params){
if(!params.hasOwnkey())continue
queryString.append(key, params[key])
}
then you can get your nicely formatted query string by saying
queryString.toString()
The accepted answer works, but if you have more params than one it doesn't generalize. I suggest the following approach, which also handles array parameters:
let route = 'http://test.url.com/offices/search';
if (method == 'GET' && params) {
const query = Object.keys(params)
.map((k) => {
if (Array.isArray(params[k])) {
return params[k]
.map((val) => `${encodeURIComponent(k)}[]=${encodeURIComponent(val)}`)
.join('&');
}
return `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`;
})
.join('&');
route += `?${query}`;
}

Resources