venom-vo
v1.1.1
Published
一个基于 TypeScript 装饰器和反射机制的VO数据处理类库
Readme
Venom 数据处理系统
一个基于 TypeScript 装饰器和反射机制的数据处理类库,类似于 NestJS 的依赖注入系统,支持 JSON 数据填充、类型转换和字段标签化。
特性
- 🚀 基于 TypeScript 装饰器的字段定义
- 📝 自动类型推断和元数据收集
- 🏷️ 字段标签化(label 方法)
- 🎯 枚举支持和自定义格式化
- 📦 预设配置支持
安装依赖
pnpm add reflect-metadata
pnpm add -D @types/node
pnpm add -D jest ts-jest @types/jest使用 npm 可替换为
npm install reflect-metadata与npm install --save-dev jest ts-jest @types/jest。
运行测试
pnpm test或使用 npm:
npm test核心功能
1. 实例创建
推荐使用静态 create 方法:
const user = User.create(data); // 推荐方式分步骤创建:
const user = new User();
user.fromJson(data);基本用法
1. 定义数据类
import { Venom, field } from 'venom-vo';
import { Enum } from 'enum-plus';
const Gender = Enum({
MALE: {
label: '男',
value: 1,
},
FEMALE: {
label: '女',
value: 2,
},
});
class BaseUser extends Venom {
@field()
name?: string;
@field({ enum: Gender })
gender?: number;
@field('date') // 使用预设配置
birthDate?: string;
@field({
from: (v) => `$${v.toFixed(2)}`,
})
salary?: number;
}
class User extends BaseUser {
@field({
type: BaseUser,
})
children?: BaseUser[];
}2. 使用数据类
// 推荐使用静态 create 方法创建实例
const user = User.create({
name: 'Alice',
gender: 1,
birthDate: '1990-01-01',
salary: 5000,
children: [{ name: 'Bob', gender: 1, birthDate: '2010-01-01' }],
});
// 或者分步骤创建
const user2 = new User();
user2.fromJson(apiResponseData);
// 获取字段值(原始值)
console.log(user.name); // "Alice"
console.log(user.gender); // 1 (原始值)
console.log(user.getLabel('gender')); // "男" (转换后的标签)field 装饰器选项
基本选项
interface FieldOptions {
enum?: any; // 枚举对象
toView?: (value: any) => any; // 转换为视图显示时的转换函数
toForm?: (value: any) => any; // 转换为表单数据时的转换函数
type?: any; // 手动指定类型,用于数组元素类型
}枚举支持
import { Enum } from 'enum-plus';
import { Venom, field } from './index';
// 定义性别枚举
const Gender = Enum({
男: 1,
女: 2,
});
class User extends Venom {
@field({ enum: Gender })
gender?: number;
}
const user = new User({ gender: 1 });
console.log(user.gender); // "男"自定义转换
class User extends Venom {
@field({
toForm: (v) => new Date(v), // JSON 字符串转 Date 对象
})
createdAt?: string;
}预设配置
支持以下预设配置字符串:
'date'- 日期格式化为 YYYY-MM-DD'datetime'- 日期时间格式化为 YYYY-MM-DD HH:mm:ss'time'- 时间格式化为 HH:mm:ss'price'- 价格处理(分转元,保留两位小数)'currency'- 货币格式化(分转元,带 ¥ 符号)'string'- 字符串处理'number'- 数字处理'boolean'- 布尔值处理
class Product extends Venom {
@field('date')
createDate?: string; // "2024-01-15"
@field('datetime')
updateTime?: string; // "2024-01-15 10:30:00"
@field('time')
openTime?: string; // "09:30:00"
@field('price')
price?: number; // "99.99" (分转元)
@field('currency')
originalPrice?: number; // "¥199.99" (带货币符号)
}Venom 类方法
fromJson(data: any)
从 JSON 数据填充实例字段
getLabel(fieldName: string): any
获取字段的转换后标签(经过枚举转换或 toView 函数处理的值)。
const user = User.create({
name: 'Alice',
gender: 1,
age: 18,
});
// 字段直接存储原始值
console.log(user.gender); // 1
console.log(user.age); // 18
// 获取转换后的标签
console.log(user.getLabel('gender')); // '男'
console.log(user.getLabel('age')); // 19 (经过toView函数转换)toView(): any
输出实例经过配置转换的 JSON 对象,支持嵌套对象和数组。
class SubUser extends Venom {
@field()
title?: string;
@field({
toView: (v) => v.toUpperCase(),
})
description?: string;
}
class User extends Venom {
@field()
name?: string;
@field({ enum: Gender })
gender?: number;
@field({
toView: (v) => v + 1,
})
age?: number;
@field({ type: SubUser })
profile?: SubUser;
@field({ type: SubUser })
children?: SubUser[];
}
const user = User.create({
name: 'Alice',
gender: 1,
age: 18,
profile: {
title: 'Profile Title',
description: 'hello world',
},
children: [{ title: 'Child 1', description: 'first child' }],
});
// 输出转换后的JSON对象
console.log(user.toView());
// {
// "name": "Alice",
// "gender": "男",
// "age": 19,
// "profile": {
// "title": "Profile Title",
// "description": "HELLO WORLD"
// },
// "children": [
// {
// "title": "Child 1",
// "description": "FIRST CHILD"
// }
// ]
// }toForm(): any
输出适合表单使用的 JSON 对象,支持自定义转换:
class User extends Venom {
@field({
toForm: (v) => String(v), // 表单中转为字符串
})
age?: number;
@field({
toForm: (v) => v.toLowerCase(), // 表单中转为小写
})
description?: string;
@field({ type: SubUser })
profile?: SubUser;
@field({ type: SubUser })
children?: SubUser[];
}
const user = User.create({
age: 18,
description: 'HELLO WORLD',
profile: {
title: 'Profile Title',
description: 'hello world',
},
children: [{ title: 'Child 1', description: 'first child' }],
});
// 输出适合表单的JSON对象
console.log(user.toForm());
// {
// "age": "18", // 经过 toForm 转换为字符串
// "description": "hello world", // 转为小写
// "profile": {...}, // 嵌套对象也会调用 toForm
// "children": [...] // 数组中的嵌套对象也会转换
// }static getFields(): FieldMetadata[]
获取类的字段元数据
字段值和标签
字段存储原始值,使用 getLabel 方法获取转换后的标签:
const user = User.create({ name: 'Alice', gender: 1 });
// 获取字段值(原始值)
console.log(user.name); // "Alice"
console.log(user.gender); // 1 (原始值)
// 获取转换后的标签
console.log(user.getLabel('gender')); // "男" (枚举转换后的标签)嵌套对象支持
class Address extends Venom {
@field()
street?: string;
@field()
city?: string;
}
class User extends Venom {
@field()
name?: string;
@field()
address: Address = new Address();
@field({
type: Address,
})
addresses: Address[];
}
const user = new User({
name: 'Alice',
address: { street: '123 Main St', city: 'New York' },
addresses: [{ street: '456 Oak Ave', city: 'Boston' }],
});注意事项
需要在
tsconfig.json中启用装饰器支持:{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } }必须导入
reflect-metadata字段类型需要明确定义,以便正确获取元数据
