如何将typescript对象序列化为JSON字符串,以便按特定顺序(未排序)序列化所有属性?
顺序可以是接口/类顺序,或者如果可能的话,使用实验装饰器!
有什么想法吗?
示例:
interface Root {
id: string;
name: string;
description: string;
childs: Child[];
}
interface Child {
id: string;
name: string;
description: string
}
const root = ...
JSON.stringify(root, null, 2);
结果:
{
"id": "1000",
"name": "root name",
"description": "root description",
"childs": [{
"id": "9000",
"name": "child name 1",
"description": "child description 1"
},{
"id": "9001",
"name": "child name 2",
"description": "child description 2"
}]
}
答案 0 :(得分:0)
您可以使用实验装饰器实现此目的,例如:使用Angular中的ReflectionCapabilities
和Decorators
类。
首先,声明一个属性装饰器,如下所示:
export class Serialized {
}
export interface SerializedDecorator {
(obj: Serialized): TypeDecorator;
new(obj: Serialized): Serialized;
}
export const Serialized: SerializedDecorator =
makePropDecorator('Serialized', (args) => args, Serialized);
您的数据模型如下所示:
class Root {
@Serialized({})
id: string;
@Serialized({})
name: string;
@Serialized({})
description: string;
@Serialized({})
childs: Child[];
}
class Child {
@Serialized({})
id: string;
@Serialized({})
name: string;
@Serialized({})
description: string
}
现在,要获取属性信息并将字符串放在一起,请执行以下操作:
export function stringifyOrdered(obj: any): string {
if(!obj || !obj.__proto__ || !obj.__proto__.constructor)
return "";
let serialized = "{";
const reflect = new ReflectionCapabilities();
// this gives you the ordered list of properties:
for (let propMetadata in reflect.propMetadata(obj.__proto__.constructor)) {
/* put together the stringified object,
recursively call the serialize function if the value type is object */
if(obj[propMetadata] instanceof Array){
serialized += `"${propMetadata}": [`;
for(let item of <Array<any>>obj[propMetadata]){
if(['string', 'number', 'boolean'].includes(typeof item)){
serialized += `"${item}", `
} else if (typeof item == 'object'){
serialized += `${stringifyOrdered(item)}, `
}
}
serialized = serialized.substr(0, serialized.length - 2);
serialized += "], ";
}else{
if(["string", "number", "boolean"].includes(typeof obj[propMetadata])){
serialized += `"${propMetadata}": "${obj[propMetadata]}", `
} else if (typeof obj[propMetadata] == 'object'){
serialized += `"${propMetadata}": ${stringifyOrdered(obj[propMetadata])}, `
}
}
}
serialized = serialized.substr(0, serialized.length - 2);
return serialized + "}";
}
我在自己的项目中使用ReflectionCapabilities
和Decorators
。您可以从GitHub获取它:https://github.com/angular/angular/blob/master/packages/core/src/reflection/reflection_capabilities.ts和https://github.com/angular/angular/blob/master/packages/core/src/util/decorators.ts
更新:我测试了上面的代码,它对我有用。随时随地使用它。
一些背景信息:从TypeScript转换为JavaScript时,属性声明会被剥离。保留此信息的一种方法是注释所有属性。这只能在类中进行,而不能在接口中进行。