我在TypeScript中使用getter / setter访问器。由于变量和方法不可能具有相同的名称,因此我开始在变量前加一个较低的短划线,如许多示例所示:
private _major: number;
get major(): number {
return this._major;
}
set major(major: number) {
this._major = major;
}
现在,当我使用JSON.stringify()方法将对象转换为JSON字符串时,它将使用变量名作为键:_major。
由于我不希望JSON文件的所有键都以下划线作为前缀,因此有可能使TypeScript使用getter方法的名称(如果可用)吗?或者是否有其他方法可以使用getter / setter方法,但仍然可以生成干净的JSON输出?
我知道有些方法可以在将JSON密钥写入字符串输出之前手动修改它们。如果有更简单的解决方案,我很好奇。
Here is a JSFiddle演示了当前的行为。
答案 0 :(得分:8)
基于@ Jan-Aagaard解决方案,我测试了这个
public toJSON(): string {
let obj = Object.assign(this);
let keys = Object.keys(this.constructor.prototype);
obj.toJSON = undefined;
return JSON.stringify(obj, keys);
}
以便使用toJSON方法
答案 1 :(得分:3)
不,你不能让JSON.stringify
使用getter / setter名称而不是属性名称。
但你可以这样做:
class Version {
private _major: number;
get major(): number {
return this._major;
}
set major(major: number) {
this._major = major;
}
toJsonString(): string {
let json = JSON.stringify(this);
Object.keys(this).filter(key => key[0] === "_").forEach(key => {
json = json.replace(key, key.substring(1));
});
return json;
}
}
let version = new Version();
version.major = 2;
console.log(version.toJsonString()); // {"major":2}
答案 2 :(得分:2)
我认为迭代属性和字符串操作是危险的。我会使用对象本身的原型,如下所示:
public static toJSONString() : string {
return JSON.stringify(this, Object.keys(this.constructor.prototype)); // this is version class
}
答案 3 :(得分:0)
我已经编写了一个小型库ts-typed,该库生成用于运行时键入目的的getter / setter。使用JSON.stringify()时,我遇到了同样的问题。因此,我通过添加一种序列化程序并建议实现一种toString(在Java中)来解决该问题,购买将其称为toJSON。
这里是一个示例:
import { TypedSerializer } from 'ts-typed';
export class RuntimeTypedClass {
private _major: number;
get major(): number {
return this._major;
}
set major(major: number) {
this._major = major;
}
/**
* toString equivalent, allows you to remove the _ prefix from props.
*
*/
toJSON(): RuntimeTypedClass {
return TypedSerializer.serialize(this);
}
}
答案 4 :(得分:0)
一个老问题的新答案。对于 getter/setter 没有私有字段的情况,或者私有字段名称与 getter/setter 不同的情况,我们可以使用 Object.getOwnPropertyDescriptors
从原型中查找 get
方法。
https://stackoverflow.com/a/60400835/2325676
我们在这里添加了 toJSON
函数,以便它与其他海报提到的 JSON.stringify
一起使用。这意味着我们不能在 JSON.stringify()
内调用 toJSON
,因为它会导致无限循环,所以我们使用 Object.assign(...)
我还删除了 _private
字段作为整理措施。您可能希望删除不想包含在 JSON 中的其他字段。
public toJSON(): any {
//Shallow clone
let clone: any = Object.assign({}, this);
//Find the getter method descriptors
//Get methods are on the prototype, not the instance
const descriptors = Object.getOwnPropertyDescriptors(Object.getPrototypeOf(this))
//Check to see if each descriptior is a get method
Object.keys(descriptors).forEach(key => {
if (descriptors[key] && descriptors[key].get) {
//Copy the result of each getter method onto the clone as a field
delete clone[key];
clone[key] = this[key]; //Call the getter
}
});
//Remove any left over private fields starting with '_'
Object.keys(clone).forEach(key => {
if (key.indexOf('_') == 0) {
delete clone[key];
}
});
//toJSON requires that we return an object
return clone;
}