Receiving error when trying to use JSON.parse from internal storage data - javascript

My classmates and I are receiving the following error message when trying to use JSON.parse with data from internal storage. The code is given to us by our instructor so not sure what the issue is.
internal storage should hold nothing and initialize "pageViews" with 0 or if there is data in internal storage it should be an array.
Uncaught SyntaxError: Unexpected token o in JSON at position 1 at
JSON.parse () at HTMLDocument.addPageView
HERE IS OUR CODE.
const pageViewsKeyName = "pageViews";
function addPageView() {
let pageViews = localStorage.getItem(pageViewsKeyName);
let arr = [];
if (pageViews && pageViews.length > 0) {
// get the array stored in local storage at pageViewsKeyName
arr = JSON.parse(pageViews);
// now we're able to insert an item in the page view data
let newPageData = {
"path": window.location.pathname,
"timestamp": moment()
};
// now add new page data to the array
arr.push(newPageData);
// finally, we want to update our storage with the most up to date array
localStorage.setItem(pageViewsKeyName, arr);
}
}

JSON.parse is used to parse the string JSON value as JSON object. Looks like the pageViews already contains JSON object. Therefore you don't need to parse it. You can console.log(pageViews) to confirm that.

Yes, console.log(typeof PageViews) and check out what is it's data type.
If it's an arry:
arr.push(PageViews[0]); // TODO for-loop to push all views into arr
If it's an object:
arr.push(PageViews)

Related

Is there a way to configure the Firestore timestamp outputs?

I'm using Firestore to keep timestamps such as this log output:
{
my_timestamp: Timestamp { seconds: 1676783325, nanoseconds: 209000000 },
product_name: 'Android'
}
I'm reading the values in my web app like this:
...
const result = []
productDocs.forEach((productDoc: DocumentData) => {
result.push({ id: productDoc.id, ...productDoc.data() })
})
return result
...
But I get an error:
Server Error
Error: Error serializing `.productDoc[0].my_timestamp` returned from `getStaticProps` in "/[pid]".
Reason: `object` ("[object Object]") cannot be serialized as JSON. Please only return JSON serializable data types.
It seems to me that the Timestamp object is not easily accepted as part of the object. My solution is to iterate through each Object.entries(productDoc).forEach(productData)... and reformat the Timestamp object and then push on an array.
This seems like a manual way to go about this so I'd like to make sure I'm parsing the timestamp object properly and I'm not missing some way where I can just read the whole result from Firebase as an object with doing nothing to the timestamp.
It seems How do I convert a Firestore date/Timestamp to a JS Date()? is the only way where I have to take the object apart and convert the values.
I didn't see a way to do this on https://firebase.google.com/docs/reference/js/firestore_.timestamp other than just converting the Firebase object.
Using the DocumentSnapshot type should solve your problem:
const result = []
productDocs.forEach((productDoc: DocumentSnapshot) => {
result.push({ id: productDoc.id, ...productDoc.data() })
}
A DocumentSnapshot contains data read from a document in your Firestore database while a DocumentData is to be used with the setDoc() method.

Using MongoDB Stitch webhook service function, how can I convert the returned "insertedId" to string?

I'm creating MongoDB Stitch http services (using the 3rd Party Services > Incoming Webhooks > Function Editor) for a simple CRUD application and I am trying to insertOne() document and then return the document id as a string.
The insertion works as expected and I await the result and store it in a variable.
const result = await collection.insertOne(payload.query)
const id = result.insertedId
The problem is trying to convert this id to string. I'm guessing it's due to my lack of understanding the MongoDB Extended JSON and BSON types, etc. I've read all parts of the documentation that I thought could provide a solution here.
I've tried the following to convert the return value to a string:
id.toString() // logs as a string, but is an object { $oid: '507c7f79bcf86cd7994f6c0e' }
id.valueOf() // logs as a string, but is an object { $oid: '507c7f79bcf86cd7994f6c0e' }
id['$oid'] // undefined
Object.values(id.insertedId) // throws error: {"message":"'values' is not a function"}
id.str // undefined
result.str // undefined
Not sure what else to try and would really appreciate if someone can point me in the right direction here to provide a solution.
Thank you in advance.
Found a solution after noticing this section of the documentation:
MONGODB STITCH > Functions > Reference > JSON & BSON
const result = await collection.insertOne(payload.query)
const id = JSON.stringify(
JSON.parse(
EJSON.stringify(result.insertedId)
).$oid
).replace(/\W/g,'');
Seems a bit hacky just for getting the id of the document into a string, but it will work for now.

Access keys within Javascript object

I have an iframe that I am sending a data object to that has an id_token and access_token in it. The data object arrives fine and I am able to pull the object with an event listener. Sample code is below. However, when I receive the object I try to access items in the object and get an undefined. I have included an obfiscated image of the object that I receive in the javascript console.
I have included snippets of different things I have tried but to no avail.
Displaying the iframe
const data = {
id_token: idToken,
access_token: accessToken
};
Application that is being displayed in the iframe
useEffect(() => {
window.addEventListener('message', receiveMessage, false);
function receiveMessage(event) {
if (event.origin !== 'https://example.com") {
return;
}
let eventData = event.data;
console.log(eventData); // The response is the object that is returned in the image below
console.log(eventData.id_token) // The response is undefined
console.log(eventData[id_token]) // undefined
console.log(eventData["id_token"] // undefined
console.log(eventData['"id_token"'] // undefined
// All three of these displayed each individual character of the object.
Object.keys(eventData).forEach(key => console.log(key, eventData[key]));
Object.getOwnPropertyNames(eventData).forEach(key =>
console.log(key, eventData[key])
);
for (let key in eventData) console.log(key, eventData[key]);
}
}, []);
Basically I need to extract the access and id tokens for authentication. If there is a better way to do this I am all ears.
Screenshot of object that is being returned:
When receiving "objects" from requests or events in Javascript it can be easy to mistake actual objects from a string-serialized form of an object in JSON notation.
It can be difficult to tell which is which when logging to the console as the example shows but browser-tools can be more helpful as the image shows.
If you need to convert your JSON back to an object then use JSON.parse() and handle any exceptions.
obj = {a:100}
json = JSON.stringify(obj);
// print an object
console.log('Printing an Object:')
console.log(obj)
// print json
console.log('Printing a JSON string:')
console.log(json)

Changing an array entry within a json object

I've pulled json from a File using NodeJS's fs.createReadStream() and I'm now finding difficulty writing data back into the File (already parsing and then stringifying as appropriate).
The Discord-Bot I'm developing deletes text-channels then 'recreates' them (with the same title) to clear chat - it grabs the channel IDs dynamically and puts them in a file, until the channels are deleted.
However, the file-writing procedure ends up in errors.
This was my first attempt:
let channels_json = fs.createReadStream()
//let channels_json = fs.readFileSync(`${__dirname}\\..\\json\\channels.json`);
let obj = (JSON.parse(channels_json)).channelsToClear;
let i = 0;
obj.forEach(id => {
i++;
if(id === originalId){
obj[i] = channela.id;
}
});
obj += (JSON.parse(channels_json)).infoChannel;
obj += "abc";
json = JSON.stringify(obj);
channels_json.write(json);
This was my second:
let id_to_replace = message.guild.channels.get(channels[channel]).id;
//let channels_json = fs.readFileSync(`${__dirname}\\..\\json\\channels.json`);
let obj;
let channels_json = fs.createReadStream(`${__dirname}\\..\\json\\channels.json`,function(err,data){
if (err) throw err;
obj = JSON.parse(data);
if (obj["channelsToClear"].indexOf(id_to_replace) > -1) {
obj["channelsToClear"][obj["channelsToClear"].indexOf(id_to_replace)] = channela.id;
//then replace the json file with new parsed one
channels_json.writeFile(`${__dirname}\\..\\json\\channels.json`, JSON.stringify(obj), function(){
console.log("Successfully replaced channels.json contents");
});
//channels_json.end();
}
});
The final outcome was to update the 'channelsToClear' array within the json file with new channel-IDs. Console/Node output varied, all of which had to do with "create channels with an options object" or "Buffer.write" (all irrelevant) - the json file remained unchanged..
You're using Streams incorrectly. You can't write back out through a read stream.
For a simple script type thing, streaming is probably overkill. Streams are quite a bit more complicated and while worth it for high-efficienty applications but not for something that looks like it is going to be relatively quick.
Use the fs.readFileSync and fs.writeFileSync to get and write the data instead.
As far as your actual searching for and replacing the channel, I think either approach would work, but assuming there is only ever going to be one replacement, the second approach is probably better.

Ionic 1 - ngCordovaNativeStorage issue?

how's it going?
I've using this plugin for a long time, but today I needed to do some notifications in my app. I need to store my data in device and then, when I got internet connection, I'll send this for my servers. But ok, this is not important.
What I'm trying to do is:
Get my data from server;
Store my data in device using nativeStorage;
Getting data and putting in my storage
myFactory.getMyData().then(function(success) {
$cordovaNativeStorage.setItem("mydata", success);
}, function(err) {...});
OK, my data was correctly stored. Next I'll loop in thru this data and show in view.
$cordovaNativeStorage.getItem("mydata").then(function (success)
{
for (var i in success)
{
$scope.myData.push(success[i]);
}
}, function (err){
getMyData(); // function who will get my data from server
});
OK until now.
Next I'll send this data to another view and show my data. But when I do ANY modifications in that data (even if I change directly in object or in nativeStorage), that modification do not persists if I back to the main view.
$cordovaNativeStorage.getItem("myData").then(function (success){
success[myIndex].anyProperty = 'abc';
});
Is that a bug or am I not understanding something?
When you're calling $cordovaNativeStorage.setItem(), Native storage actually save JSON string rather than JSON object.Same with $cordovaNativeStorage.getItem(), it will return JSON string. Thus, you must parse it first before manipulating the object .
$cordovaNativeStorage.getItem("myData").then(function (jsonString){
if (jsonString) {
var jsonObj = JSON.parse(jsonString);
jsonObj.anyProperty = 'abc';
}
});

Categories