如何序列化对象并将其转换回与原始对象相同的 class
How to serialize an object and cast it back to the same class as the original object
我是 JavaScript 的新手,如果我问的不是 "how you do it in JavaScript",请多多包涵。欢迎就其他方法提出建议。
我有一个名为 State
的 class,我需要使用 JSON.stringify()
序列化那个 class 的对象。下一步是将它们反序列化回一个对象。但是,我的 class 使用 setter 和 getter。
我面临的问题是,在我反序列化这些对象后,setter 和 getter 似乎消失了。我只是不知道如何正确地将序列化对象转回 class 的对象,以便它们的行为与直接使用 new
创建的对象完全相同。
在另一种语言中,我会将这些对象转换为 State
对象。我找不到似乎可以这样工作的 JavaScript 机制。
代码如下所示:
class State {
constructor(href) {
this.url = href;
}
set url(href) {
this._url = new URL(href);
this.demoParam = this._url.searchParams.get("demoParam");
}
get url() {
return this._url;
}
set demoParam(value) {
let param = parseInt(value, 10);
if(isNaN(param)) {
param = 2;
}
console.log("Setting 'demoParam' to value " + param);
this._demoParam = param;
}
get demoParam() {
return this._demoParam;
}
toJSON() {
let stateObject = {};
const prototypes = Object.getPrototypeOf(this);
for(const key of Object.getOwnPropertyNames(prototypes)) {
const descriptor = Object.getOwnPropertyDescriptor(prototypes, key);
if(descriptor && typeof descriptor.get === 'function') {
stateObject[key] = this[key];
}
}
return stateObject;
}
}
let originalState = new State(window.location.href);
let newState1 = JSON.parse(JSON.stringify(originalState));
newState1.demoParam = 12;
let newState2 = Object.create(State.prototype, Object.getOwnPropertyDescriptors(JSON.parse(JSON.stringify(originalState))));
newState2.demoParam = 13;
let newState3 = Object.assign(new State(window.location.href), JSON.parse(JSON.stringify(originalState)));
newState3.demoParam = 14;
let newState4 = Object.setPrototypeOf(JSON.parse(JSON.stringify(originalState)), State.prototype);
newState4.demoParam = 15;
我希望每次设置 newStateX
对象的 demoParam
属性 时,我都会看到一条控制台日志消息。然而。我只看到它两次,即每个 new State(window.location.href)
语句。
我已经使用了问题的答案。但是,它没有按预期工作。
当您序列化一个对象时,您会触发 class' 实例的 toString
或 toJSON
方法,最终只会得到一个 "dumb" JSON 表示您的可枚举属性。
如果您想重新创建一个行为与序列化之前一样的实例,您需要在 toJSON 函数中设置一个额外的 key/value 对,例如 ___internalType: 'state'
和然后稍后使用例如。一个 switch
语句,用于使用 new MyClass(serializedData)
重新创建您的特定 class 并传入您的序列化实例。在 class 的构造函数中,您设置了所有需要的属性,瞧,您又拥有了 "old" 实例
/编辑:澄清你的控制台日志没有显示的原因是因为你没有重新创建你的 class 的实例,而只是创建一个新的普通对象。
您可以使用 Object.assign 将普通对象数据复制到 class 的 "empty" 新实例中,代码如下:
function cast(o) {
if (!o._cls) return o;
var _cls = eval(o._cls);
return Object.assign(new _cls(), o);
}
在 JavaScript 中,我个人喜欢避免对我的数据对象使用 classes。 TypeScript 提供了一些更好的机会来解决这个问题,其中之一是 TypedJSON:
我是 JavaScript 的新手,如果我问的不是 "how you do it in JavaScript",请多多包涵。欢迎就其他方法提出建议。
我有一个名为 State
的 class,我需要使用 JSON.stringify()
序列化那个 class 的对象。下一步是将它们反序列化回一个对象。但是,我的 class 使用 setter 和 getter。
我面临的问题是,在我反序列化这些对象后,setter 和 getter 似乎消失了。我只是不知道如何正确地将序列化对象转回 class 的对象,以便它们的行为与直接使用 new
创建的对象完全相同。
在另一种语言中,我会将这些对象转换为 State
对象。我找不到似乎可以这样工作的 JavaScript 机制。
代码如下所示:
class State {
constructor(href) {
this.url = href;
}
set url(href) {
this._url = new URL(href);
this.demoParam = this._url.searchParams.get("demoParam");
}
get url() {
return this._url;
}
set demoParam(value) {
let param = parseInt(value, 10);
if(isNaN(param)) {
param = 2;
}
console.log("Setting 'demoParam' to value " + param);
this._demoParam = param;
}
get demoParam() {
return this._demoParam;
}
toJSON() {
let stateObject = {};
const prototypes = Object.getPrototypeOf(this);
for(const key of Object.getOwnPropertyNames(prototypes)) {
const descriptor = Object.getOwnPropertyDescriptor(prototypes, key);
if(descriptor && typeof descriptor.get === 'function') {
stateObject[key] = this[key];
}
}
return stateObject;
}
}
let originalState = new State(window.location.href);
let newState1 = JSON.parse(JSON.stringify(originalState));
newState1.demoParam = 12;
let newState2 = Object.create(State.prototype, Object.getOwnPropertyDescriptors(JSON.parse(JSON.stringify(originalState))));
newState2.demoParam = 13;
let newState3 = Object.assign(new State(window.location.href), JSON.parse(JSON.stringify(originalState)));
newState3.demoParam = 14;
let newState4 = Object.setPrototypeOf(JSON.parse(JSON.stringify(originalState)), State.prototype);
newState4.demoParam = 15;
我希望每次设置 newStateX
对象的 demoParam
属性 时,我都会看到一条控制台日志消息。然而。我只看到它两次,即每个 new State(window.location.href)
语句。
我已经使用了
当您序列化一个对象时,您会触发 class' 实例的 toString
或 toJSON
方法,最终只会得到一个 "dumb" JSON 表示您的可枚举属性。
如果您想重新创建一个行为与序列化之前一样的实例,您需要在 toJSON 函数中设置一个额外的 key/value 对,例如 ___internalType: 'state'
和然后稍后使用例如。一个 switch
语句,用于使用 new MyClass(serializedData)
重新创建您的特定 class 并传入您的序列化实例。在 class 的构造函数中,您设置了所有需要的属性,瞧,您又拥有了 "old" 实例
/编辑:澄清你的控制台日志没有显示的原因是因为你没有重新创建你的 class 的实例,而只是创建一个新的普通对象。
您可以使用 Object.assign 将普通对象数据复制到 class 的 "empty" 新实例中,代码如下:
function cast(o) {
if (!o._cls) return o;
var _cls = eval(o._cls);
return Object.assign(new _cls(), o);
}
在 JavaScript 中,我个人喜欢避免对我的数据对象使用 classes。 TypeScript 提供了一些更好的机会来解决这个问题,其中之一是 TypedJSON: