I have 2 objects:
const subscription = {
endpoint: "dfksjfklsjkld",
keys: {
pkey: "dfsfsdfsf",
auth: "dfsdfsdfsd"
}
};
const extra = {
email: "dfsdfs",
ip:"231342.342.342.34"
};
I would like to put the extra
object inside subscription, so it looks like:
subsciption = {
endpoint: ......
keys: {...},
extra: {
email:....,
ip: .....
}
}
then I need to send it as body of a http request:
const response = await fetch(url, {
method: "PUT",
mode: "no-cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
redirect: "follow",
referrerPolicy: "no-referrer",
body: JSON.stringify(subscription),
});
but I found no matter what I do, I always lose the extra property inside subscription in the process of JSON.stringify()
.
I know the cause: it's because that the properties in extra object are not enumerable.
So far, I have tried:
1.use the spread:
newSub = {
...subscription,
...extra
}
but the content of newSub will be exactly same with extra, the properties of subscription are all lost.
2.add toJSON function into the place where I generate the extra object
getExtra() : {
.......
return {
city: ipObject.city,
country: ipObject.country_name,
ip: ipObject.ip,
lat: ipObject.latitude,
lng: ipObject.longitude,
org: ipObject.org,
postal: ipObject.postal,
region: ipObject.region,
toJSON: () => {
return this;
}
};
}
no effect at all.
I attach my code here:
async function updateSubscription() {
try {
const allowed = await askForPermission();
if (!allowed) return;
let subscription = await getSubscription();
if (!subscription) return;
// email
const email = getEmail();
if (!email || !validateEmail(email)) {
alert("huh...so how are you going to receive notifications?");
return;
}
// ip
let ipObject = await getIP();
let extra = {};
if (ipObject) {
ipObject.email = email;
extra = ipObject;
} else {
extra.email = email;
}
console.log("extra: ", extra);
// var newSubscription = Object.assign({}, subscription, {extra});
// const newSubscription = {
// ...subscription,
// extra
// };
let newSubscription = subscription;
newSubscription["extra"] = extra;
console.log("new subscription1: ", newSubscription);
console.log("new subscription1 stringified: ", JSON.stringify(newSubscription));
const successful = await saveRegistration(newSubscription);
if (successful) alert("you have successfully subscribed to the DC monitor");
else alert("shit happens, try it later");
} catch (err) {
console.log("updateSubscription() failed: ", err);
}
}
async function getSubscription() {
console.log("try to get subscription");
try {
const swRegistration = await navigator.serviceWorker.ready;
const pushSubscription = await swRegistration.pushManager.getSubscription();
console.log("pushSubscription: ", pushSubscription);
return pushSubscription;
} catch (error) {
console.log("getSubscription() error: ", error);
return null;
}
}
1.Tried 1 more approach:
var newSubscription = Object.assign({}, subscription, {extra});
console.log("subscription: ", newSubscription);
console.log("subscription stringified: ", JSON.stringify(newSubscription));
here is the output screenshot:
2.Also this one:
const newSubscription = {
...subscription,
extra
};
console.log("new subscription: ", newSubscription);
console.log("new subscription stringified: ", JSON.stringify(newSubscription));
And here is the screenshot of output:
3.with string index approach:
let newSubscription = subscription;
newSubscription["extra"] = extra;
console.log("new subscription1: ", newSubscription);
console.log("new subscription1 stringified: ", JSON.stringify(newSubscription));
If mutating subscription
is OK, you can just use:
subscription['extra'] = extra;
If you want a new object, you can use:
const subscriptionObject = Object.assign({}, subscription, { extra });
EDIT: Since you are working with the Push API, the properties in PushSubscription
are not enumerable. So the subscription
object does not behave quite like a normal object, which is why the suggested approaches have not been working.
However, you can serialize the push subscription using PushSubscription.toJSON()
first to serialize it to a "normal" object, then use one of the suggested techniques:
subscriptionObject = Object.assign({}, subscription.toJSON(), { extra });