JSON.stringify() 丢失嵌套属性我知道原因但不知道答案
JSON.stringify() losing nested properties I know the cause but don't know the answer
我有 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()
的过程中丢失额外的属性内部订阅。
我知道原因:因为extra对象中的属性是不可枚举的。
到目前为止,我已经尝试过:
1.use 点差:
newSub = {
...subscription,
...extra
}
但是newSub的内容会和extra一模一样,subscription的属性都丢失了
2.add 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.Tried 1 种方法:
var newSubscription = Object.assign({}, subscription, {extra});
console.log("subscription: ", newSubscription);
console.log("subscription stringified: ", JSON.stringify(newSubscription));
这里是输出截图:
2.Also这个:
const newSubscription = {
...subscription,
extra
};
console.log("new subscription: ", newSubscription);
console.log("new subscription stringified: ", JSON.stringify(newSubscription));
这是输出的屏幕截图:
3.with字符串索引方式:
let newSubscription = subscription;
newSubscription["extra"] = extra;
console.log("new subscription1: ", newSubscription);
console.log("new subscription1 stringified: ", JSON.stringify(newSubscription));
如果变异 subscription
没问题,你可以使用:
subscription['extra'] = extra;
如果你想要一个新对象,你可以使用:
const subscriptionObject = Object.assign({}, subscription, { extra });
编辑: 由于您使用的是 Push API,PushSubscription
中的属性不可枚举。所以 subscription
对象的行为不像普通对象,这就是建议的方法没有奏效的原因。
但是,您可以先使用 PushSubscription.toJSON()
序列化推送订阅以将其序列化为“普通”对象,然后使用建议的技术之一:
subscriptionObject = Object.assign({}, subscription.toJSON(), { extra });
你试过了吗
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"}}"
你为什么不使用像 属性
这样的简单赋值
let subscription = {..}
const extra = {..}
然后
subscription.extra = extra;
它应该有效
这有点 hacky,但看起来我们不知道 PushSubscription
对象是如何实现的,它可能不会像您期望的那样工作...
...但是它似乎使用自己的方法(根据其 API)正确转换为 JSON,因此您可能想尝试这样的操作:
const newSub = { ...JSON.parse(subscription.toJSON()), extra };
因此,将其转换为 JSON(使用 Push API 中的 toJSON
方法)并返回“正常”javascript 对象,-然后-添加 extra
属性。
我有 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()
的过程中丢失额外的属性内部订阅。
我知道原因:因为extra对象中的属性是不可枚举的。
到目前为止,我已经尝试过:
1.use 点差:
newSub = {
...subscription,
...extra
}
但是newSub的内容会和extra一模一样,subscription的属性都丢失了
2.add 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.Tried 1 种方法:
var newSubscription = Object.assign({}, subscription, {extra});
console.log("subscription: ", newSubscription);
console.log("subscription stringified: ", JSON.stringify(newSubscription));
这里是输出截图:
2.Also这个:
const newSubscription = {
...subscription,
extra
};
console.log("new subscription: ", newSubscription);
console.log("new subscription stringified: ", JSON.stringify(newSubscription));
这是输出的屏幕截图:
3.with字符串索引方式:
let newSubscription = subscription;
newSubscription["extra"] = extra;
console.log("new subscription1: ", newSubscription);
console.log("new subscription1 stringified: ", JSON.stringify(newSubscription));
如果变异 subscription
没问题,你可以使用:
subscription['extra'] = extra;
如果你想要一个新对象,你可以使用:
const subscriptionObject = Object.assign({}, subscription, { extra });
编辑: 由于您使用的是 Push API,PushSubscription
中的属性不可枚举。所以 subscription
对象的行为不像普通对象,这就是建议的方法没有奏效的原因。
但是,您可以先使用 PushSubscription.toJSON()
序列化推送订阅以将其序列化为“普通”对象,然后使用建议的技术之一:
subscriptionObject = Object.assign({}, subscription.toJSON(), { extra });
你试过了吗
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"}}"
你为什么不使用像 属性
这样的简单赋值let subscription = {..}
const extra = {..}
然后
subscription.extra = extra;
它应该有效
这有点 hacky,但看起来我们不知道 PushSubscription
对象是如何实现的,它可能不会像您期望的那样工作...
...但是它似乎使用自己的方法(根据其 API)正确转换为 JSON,因此您可能想尝试这样的操作:
const newSub = { ...JSON.parse(subscription.toJSON()), extra };
因此,将其转换为 JSON(使用 Push API 中的 toJSON
方法)并返回“正常”javascript 对象,-然后-添加 extra
属性。