#javascript #json #stringify
#javascript #json #stringify
Вопрос:
У меня есть 2 объекта:
const subscription = {
endpoint: "dfksjfklsjkld",
keys: {
pkey: "dfsfsdfsf",
auth: "dfsdfsdfsd"
}
};
const extra = {
email: "dfsdfs",
ip:"231342.342.342.34"
};
Я хотел бы поместить extra
объект внутри подписки, чтобы он выглядел как:
subsciption = {
endpoint: ......
keys: {...},
extra: {
email:....,
ip: .....
}
}
затем мне нужно отправить его как тело http-запроса:
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),
});
но я обнаружил, что независимо от того, что я делаю, я всегда теряю дополнительное свойство внутри подписки в процессе JSON.stringify()
.
Я знаю причину: это потому, что свойства в дополнительном объекте не поддаются перечислению.
До сих пор я пытался:
1. используйте распространение:
newSub = {
...subscription,
...extra
}
но содержимое newSub будет точно таким же с extra, все свойства подписки будут потеряны.
2. добавьте функцию toJSON в место, где я создаю дополнительный объект
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;
}
};
}
никакого эффекта вообще.
Я прилагаю свой код здесь:
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. Попробовал еще 1 подход:
var newSubscription = Object.assign({}, subscription, {extra});
console.log("subscription: ", newSubscription);
console.log("subscription stringified: ", JSON.stringify(newSubscription));
вот скриншот вывода:
2. Также этот:
const newSubscription = {
...subscription,
extra
};
console.log("new subscription: ", newSubscription);
console.log("new subscription stringified: ", JSON.stringify(newSubscription));
И вот скриншот вывода:
3. с использованием подхода со строковым индексом:
let newSubscription = subscription;
newSubscription["extra"] = extra;
console.log("new subscription1: ", newSubscription);
console.log("new subscription1 stringified: ", JSON.stringify(newSubscription));
Комментарии:
1. Почему дополнительные свойства не поддаются перечислению? Что это за специальный объект?
2. что такое
subscriptionObject
?3. где
subscriptionObject
установлено?4. Ах, действительно хороший улов
5. Может быть, явно скопируйте нужные вам свойства из этого объекта? Поскольку это хост-объект, вы не можете делать никаких предположений о том, как он реализован (я думаю). Согласно спецификации, он фактически реализует свою собственную процедуру сериализации JSON. Так что, может быть, вы хотите сделать
sub = subscription.toJSON(); sub.extra = extra; JSON.stringify(sub)
вместо этого.
Ответ №1:
Если изменение subscription
в порядке, вы можете просто использовать:
subscription['extra'] = extra;
Если вам нужен новый объект, вы можете использовать:
const subscriptionObject = Object.assign({}, subscription, { extra });
РЕДАКТИРОВАТЬ: Поскольку вы работаете с Push API, свойства в PushSubscription
не поддаются перечислению. Таким образом, subscription
объект ведет себя не совсем как обычный объект, поэтому предлагаемые подходы не работают.
Однако вы можете сериализовать push-подписку с помощью PushSubscription.toJSON()
, сначала сериализуя ее в «обычный» объект, а затем используя один из предложенных методов:
subscriptionObject = Object.assign({}, subscription.toJSON(), { extra });
Комментарии:
1. привет, Сергей, я попробовал Object.assign(), но содержимое subscriptionObject перезаписано extra, все свойства объекта подписки потеряны. Пожалуйста, смотрите мой раздел обновления.
2. new также попробовал подход [«extra»], но при JSON.stringify(newSub) дополнительная часть теряется.
3. @Franva Я отредактировал свой пост теперь, когда понял, что вы работаете с Push API. Попробуйте последний фрагмент…
4. это работает для меня. Да, оказывается, проблема связана с подпиской, возвращаемой из PushAPI. Огромное спасибо за вашу помощь ~!
Ответ №2:
почему бы вам не использовать подобное простое присвоение свойства
let subscription = {..}
const extra = {..}
затем
subscription.extra = extra;
это должно сработать
Комментарии:
1. спасибо, чувак, это мой первый подход, который я попробовал. но не повезло. Я consoloe.log() newSub, я вижу там дополнительное свойство, но проблема в том, что когда JSON.stringify(newSub), он потерял дополнительное свойство.
2. я только что попробовал, и это сработало, подождите, дайте мне распечатать вас
3. я только что добавил скриншот своей консоли
4. спасибо, чувак, я попробовал это в своей консоли, и я вижу, что это работает. Я добавил свои методы, например, updateSubscription() и getSubscription() как есть без каких-либо изменений. Не могли бы вы, пожалуйста, просмотреть их и посмотреть, сможете ли вы обнаружить там какие-либо ошибки?
5. Я выяснил причину, пожалуйста, смотрите SERGEY. Ответ К. Оказывается, это проблема из PushAPI.
Ответ №3:
Это немного халтурно, но, похоже, мы не знаем, как реализован PushSubscription
объект, и он может работать не так, как вы ожидаете…
… однако, похоже, он правильно преобразуется в JSON, используя свой собственный метод (в соответствии с его API), поэтому вы можете попробовать что-то вроде этого:
const newSub = { ...JSON.parse(subscription.toJSON()), extra };
Таким образом, преобразуем его в JSON (используя toJSON
метод в Push API) и обратно в «обычный» объект javascript, а затем добавляем к нему extra
свойство.
Комментарии:
1. правильно, это потому, что PushApi реализовал свой собственный toJSON(), поэтому я должен его использовать.
2. Я не тестировал его для объекта подписки, но обычно, несмотря на его название,
toJSON
не возвращает JSON. Он возвращает значение, которое может быть сериализовано в JSON. ПоэтомуJSON.parse
здесь может не сработать (это не должно быть необходимо). developer.mozilla.org/en-US/docs/Web/JavaScript/Reference /…
Ответ №4:
Вы пробовали
newSub = {
...subscription, extra
}
в этом случае вам не нужно добавлять дополнительные данные.
sub = JSON.stringify(newSub) should result in: "{"endpoint":"dfksjfklsjkld","keys":{"pkey":"dfsfsdfsf","auth":"dfsdfsdfsd"},"extra":{"email":"dfsdfs","ip":"231342.342.342.34"}}"
Комментарии:
1. спасибо, Геррит, пожалуйста, посмотрите Мой раздел обновления, я попробовал ваш способ, но содержимое newSub перезаписано extra, все свойства sub потеряны
2. Я добавил скриншот, потому что я не понимаю с точки зрения js, почему некоторые ключи свойств съедаются 🙂
3. Я выяснил причину, пожалуйста, смотрите SERGEY. Ответ К. Оказывается, это проблема из PushAPI