JSON.stringify for TypeScript 包含隐藏字段但不包含 public 接口的值
JSON.stringify for TypeScript includes hidden fields but not values for public interface
我似乎对使用 JSON.stringify
和接口在 TypeScript 中进行序列化有一些基本的误解,但我正在尝试设计一种导出格式以将我的一些对象序列化回服务器端表示(基类型只有数据,没有方法)。
我在几个地方读到接口提供了一种方便的导出到 JSON 的方法,但不明白应该如何完成。
这是我尝试过的一个基本示例:
interface PublicFoo {
name: string,
age: number
}
class Foo implements PublicFoo {
private _name : string;
private _age : number;
private _pin : number;
constructor(name : string, age : number, pin: number) {
this._name = name;
this._age = age;
this._pin = pin;
}
get name() {
return this._name;
}
get age() :number {
return this._age;
}
get pin() : number {
return this._pin;
}
serialize() : string {
let pubFoo : PublicFoo = this;
return (JSON.stringify(pubFoo));
}
}
我希望如果我 运行 这个:
let foo = new Foo("George", 27, 3918);
console.log(foo.serialize());
我会得到这样的东西:
{"name":"George","age":27}
但我得到的是:
{"_name":"George","_age":22,"_pin":3239}
显示私有文件名称,包括那些我不想序列化且不在 PublicFoo
界面中的名称。
无需手动构建导出即可执行此操作的正确方法是什么?您可以将对象字符串化这一事实很棒,因为实际对象又大又笨重...
stringify
似乎没有考虑吸气剂。
typescript 是否应该从接口获取提示以自动填充序列化 使用 getters 是一个不同的问题(知道接口不在纯 JS 中,因此没有默认值 行为继承)。
所以只需添加一个 toJSON()
并更改您的序列号以使用它:
toJSON = () :PublicFoo => ({name:this._name, age:this._age});
serialize = () :string => (JSON.stringify(this));
记住打字稿只是帮助程序员的打字基础设施也很好;还是JS。
没有什么是私人的
考虑到您的评论,请尝试使用 reflection 将编译时信息获取到运行时
import {keys} from 'ts-transformer-keys';
function freeze<Interface extends object>(instance :Interface) :Interface {
let output :Interface = {} as any;
for (let property of keys<Interface>())
output[property] = instance[property];
return output;
}
然后把上面的toJSON
改成toJSON = () :PublicFoo => (freeze<PublicFoo>(this));
你必须记住,typescript 本身没有运行时功能,这正是你在这里所期望的。它仅在编译时 提供类型安全 的实施。因此,如果你想看看你的打字稿实际上会做什么,你需要看看它编译成的 javascript 。 Get 方法是函数,调用时 return 一个值,就像任何函数一样,因此当您序列化对象时,您自然不会看到从此类函数编辑的值 return。怎么做?好吧,恐怕您将不得不自己编写序列化方法。
我似乎对使用 JSON.stringify
和接口在 TypeScript 中进行序列化有一些基本的误解,但我正在尝试设计一种导出格式以将我的一些对象序列化回服务器端表示(基类型只有数据,没有方法)。
我在几个地方读到接口提供了一种方便的导出到 JSON 的方法,但不明白应该如何完成。
这是我尝试过的一个基本示例:
interface PublicFoo {
name: string,
age: number
}
class Foo implements PublicFoo {
private _name : string;
private _age : number;
private _pin : number;
constructor(name : string, age : number, pin: number) {
this._name = name;
this._age = age;
this._pin = pin;
}
get name() {
return this._name;
}
get age() :number {
return this._age;
}
get pin() : number {
return this._pin;
}
serialize() : string {
let pubFoo : PublicFoo = this;
return (JSON.stringify(pubFoo));
}
}
我希望如果我 运行 这个:
let foo = new Foo("George", 27, 3918);
console.log(foo.serialize());
我会得到这样的东西:
{"name":"George","age":27}
但我得到的是:
{"_name":"George","_age":22,"_pin":3239}
显示私有文件名称,包括那些我不想序列化且不在 PublicFoo
界面中的名称。
无需手动构建导出即可执行此操作的正确方法是什么?您可以将对象字符串化这一事实很棒,因为实际对象又大又笨重...
stringify
似乎没有考虑吸气剂。
typescript 是否应该从接口获取提示以自动填充序列化 使用 getters 是一个不同的问题(知道接口不在纯 JS 中,因此没有默认值 行为继承)。
所以只需添加一个 toJSON()
并更改您的序列号以使用它:
toJSON = () :PublicFoo => ({name:this._name, age:this._age});
serialize = () :string => (JSON.stringify(this));
记住打字稿只是帮助程序员的打字基础设施也很好;还是JS。
没有什么是私人的
考虑到您的评论,请尝试使用 reflection 将编译时信息获取到运行时
import {keys} from 'ts-transformer-keys';
function freeze<Interface extends object>(instance :Interface) :Interface {
let output :Interface = {} as any;
for (let property of keys<Interface>())
output[property] = instance[property];
return output;
}
然后把上面的toJSON
改成toJSON = () :PublicFoo => (freeze<PublicFoo>(this));
你必须记住,typescript 本身没有运行时功能,这正是你在这里所期望的。它仅在编译时 提供类型安全 的实施。因此,如果你想看看你的打字稿实际上会做什么,你需要看看它编译成的 javascript 。 Get 方法是函数,调用时 return 一个值,就像任何函数一样,因此当您序列化对象时,您自然不会看到从此类函数编辑的值 return。怎么做?好吧,恐怕您将不得不自己编写序列化方法。