@airpower/transformer 2.4.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +345 -127
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,41 +9,80 @@
|
|
|
9
9
|
<a href="https://www.npmjs.com/@airpower/transformer">
|
|
10
10
|
<img src="https://img.shields.io/npm/dm/@airpower/transformer"/>
|
|
11
11
|
</a>
|
|
12
|
+
<a href="https://github.com/AirPowerTeam/AirPower-Transformer/blob/main/LICENSE">
|
|
13
|
+
<img src="https://img.shields.io/npm/l/@airpower/transformer"/>
|
|
14
|
+
</a>
|
|
12
15
|
</p>
|
|
13
16
|
|
|
14
17
|
<p align="center">
|
|
15
|
-
<a href="https://github.com/AirPowerTeam/AirPower-Transformer">Github</a>
|
|
16
|
-
<a href="https://gitee.com/air-power/AirPower-Transformer">Gitee</a>
|
|
18
|
+
<a href="https://github.com/AirPowerTeam/AirPower-Transformer">Github</a> ·
|
|
19
|
+
<a href="https://gitee.com/air-power/AirPower-Transformer">Gitee</a> ·
|
|
17
20
|
<a href="https://www.npmjs.com/package/@airpower/transformer">NPM</a>
|
|
18
21
|
</p>
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 📖 项目介绍
|
|
26
|
+
|
|
27
|
+
**AirPower-Transformer** 是一个功能强大且轻量级的 TypeScript 数据转换库,专为简化 **JSON 对象** 与 **类实例**
|
|
28
|
+
之间的双向转换而设计。该库通过装饰器提供了一种声明式的方式来控制数据转换过程,使开发者能够轻松处理复杂的嵌套对象、数组以及具有特定格式要求的数据结构。
|
|
21
29
|
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
### 🎯 核心优势
|
|
31
|
+
|
|
32
|
+
| 优势 | 说明 |
|
|
33
|
+
|-----------|----------------------------------|
|
|
34
|
+
| **零依赖** | 不依赖任何外部库,纯 TypeScript 实现,轻量级解决方案 |
|
|
35
|
+
| **类型安全** | 完全基于 TypeScript,提供完整的类型检查和智能提示 |
|
|
36
|
+
| **装饰器驱动** | 使用 TypeScript 装饰器来配置转换行为,代码清晰易懂 |
|
|
37
|
+
| **灵活配置** | 支持前缀、别名、类型转换、自定义转换逻辑等多种配置方式 |
|
|
38
|
+
| **嵌套支持** | 自动处理嵌套对象和数组的转换,支持深层嵌套结构 |
|
|
39
|
+
| **继承友好** | 支持类的继承,装饰器配置可自动继承到子类 |
|
|
40
|
+
|
|
41
|
+
---
|
|
24
42
|
|
|
25
43
|
## ✨ 主要特性
|
|
26
44
|
|
|
27
|
-
- **双向转换**:支持从 JSON
|
|
45
|
+
- **双向转换**:支持从 JSON 对象到类实例的转换(`fromJson`),以及从类实例到 JSON 对象的转换(`toJson`)
|
|
28
46
|
- **装饰器驱动**:使用 TypeScript 装饰器来配置转换行为,代码清晰易懂
|
|
29
47
|
- **前缀支持**:可以为整个类或特定字段设置前缀,适应不同 API 的命名规范
|
|
30
48
|
- **字段别名**:支持字段别名映射,解决前后端字段名不一致的问题
|
|
31
|
-
-
|
|
49
|
+
- **类型转换**:自动将 JSON 数据转换为指定的类实例,支持 String、Number、Boolean 等基础类型
|
|
32
50
|
- **嵌套对象处理**:自动处理嵌套对象和数组的转换
|
|
33
|
-
-
|
|
34
|
-
-
|
|
51
|
+
- **自定义转换逻辑**:支持自定义转换函数(`@ToClass` / `@ToJson`),满足特殊转换需求
|
|
52
|
+
- **实例方法丰富**:提供 `copy()`、`expose()`、`exclude()`、`recoverBy()` 等实用方法
|
|
53
|
+
|
|
54
|
+
---
|
|
35
55
|
|
|
36
56
|
## 💻 安装
|
|
37
57
|
|
|
38
|
-
```
|
|
58
|
+
```bash
|
|
59
|
+
# npm
|
|
39
60
|
npm install @airpower/transformer
|
|
40
|
-
|
|
61
|
+
|
|
62
|
+
# yarn
|
|
41
63
|
yarn add @airpower/transformer
|
|
42
|
-
|
|
64
|
+
|
|
65
|
+
# pnpm
|
|
43
66
|
pnpm add @airpower/transformer
|
|
44
67
|
```
|
|
45
68
|
|
|
46
|
-
|
|
69
|
+
### 环境要求
|
|
70
|
+
|
|
71
|
+
- TypeScript >= 4.0
|
|
72
|
+
- 需要在 `tsconfig.json` 中启用以下配置:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"compilerOptions": {
|
|
77
|
+
"experimentalDecorators": true,
|
|
78
|
+
"emitDecoratorMetadata": true
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 📖 快速开始
|
|
47
86
|
|
|
48
87
|
### 基础用法
|
|
49
88
|
|
|
@@ -60,15 +99,109 @@ class User extends Transformer {
|
|
|
60
99
|
const userData = { id: 1, name: 'John', email: 'john@example.com' }
|
|
61
100
|
const user = User.fromJson(userData)
|
|
62
101
|
|
|
102
|
+
console.log(user.id) // 输出: 1
|
|
103
|
+
console.log(user.name) // 输出: 'John'
|
|
104
|
+
|
|
63
105
|
// 将实例转换为 JSON
|
|
64
106
|
const json = user.toJson()
|
|
107
|
+
console.log(json) // 输出: { id: 1, name: 'John', email: 'john@example.com' }
|
|
65
108
|
```
|
|
66
109
|
|
|
67
|
-
###
|
|
110
|
+
### 完整示例
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { Alias, IgnorePrefix, Prefix, Transformer, Type } from '@airpower/transformer'
|
|
114
|
+
|
|
115
|
+
// 定义嵌套类
|
|
116
|
+
@Prefix('addr_')
|
|
117
|
+
class Address extends Transformer {
|
|
118
|
+
id!: number
|
|
119
|
+
|
|
120
|
+
@Alias('street_address')
|
|
121
|
+
street!: string
|
|
122
|
+
|
|
123
|
+
city!: string
|
|
124
|
+
country!: string
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@Prefix('role_')
|
|
128
|
+
class Role extends Transformer {
|
|
129
|
+
id!: number
|
|
130
|
+
name!: string
|
|
131
|
+
|
|
132
|
+
@IgnorePrefix()
|
|
133
|
+
permissions: string[] = []
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 主类
|
|
137
|
+
@Prefix('usr_')
|
|
138
|
+
class User extends Transformer {
|
|
139
|
+
id!: number
|
|
140
|
+
|
|
141
|
+
@Alias('full_name')
|
|
142
|
+
name!: string
|
|
143
|
+
|
|
144
|
+
email!: string
|
|
145
|
+
|
|
146
|
+
@IgnorePrefix()
|
|
147
|
+
temporaryToken!: string
|
|
68
148
|
|
|
69
|
-
|
|
149
|
+
@Type(Address)
|
|
150
|
+
homeAddress!: Address
|
|
70
151
|
|
|
71
|
-
|
|
152
|
+
@Type(Role, true)
|
|
153
|
+
roles: Role[] = []
|
|
154
|
+
|
|
155
|
+
createdAt!: Date
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 使用示例
|
|
159
|
+
const jsonData = {
|
|
160
|
+
usr_id: 1,
|
|
161
|
+
full_name: 'John Doe',
|
|
162
|
+
usr_email: 'john@example.com',
|
|
163
|
+
temporaryToken: 'abc123',
|
|
164
|
+
homeAddress: {
|
|
165
|
+
addr_id: 1,
|
|
166
|
+
street_address: '123 Main St',
|
|
167
|
+
addr_city: 'New York',
|
|
168
|
+
addr_country: 'USA'
|
|
169
|
+
},
|
|
170
|
+
roles: [
|
|
171
|
+
{
|
|
172
|
+
role_id: 1,
|
|
173
|
+
role_name: 'Admin',
|
|
174
|
+
permissions: ['read', 'write', 'delete']
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
role_id: 2,
|
|
178
|
+
role_name: 'User',
|
|
179
|
+
permissions: ['read']
|
|
180
|
+
}
|
|
181
|
+
],
|
|
182
|
+
usr_createdAt: '2023-01-01T00:00:00Z'
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// 从 JSON 创建实例
|
|
186
|
+
const user = User.fromJson(jsonData)
|
|
187
|
+
console.log(user.name) // 'John Doe'
|
|
188
|
+
console.log(user.temporaryToken) // 'abc123'
|
|
189
|
+
console.log(user.homeAddress.street) // '123 Main St'
|
|
190
|
+
console.log(user.roles.length) // 2
|
|
191
|
+
console.log(user.roles[0].permissions) // ['read', 'write', 'delete']
|
|
192
|
+
|
|
193
|
+
// 转换回 JSON
|
|
194
|
+
const jsonOutput = user.toJson()
|
|
195
|
+
console.log(JSON.stringify(jsonOutput, null, 2))
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 🛠️ 装饰器详解
|
|
201
|
+
|
|
202
|
+
### 1. `@Prefix(prefix: string)`
|
|
203
|
+
|
|
204
|
+
为类的所有字段设置统一前缀,适用于 API 返回数据带有统一前缀的场景。
|
|
72
205
|
|
|
73
206
|
```typescript
|
|
74
207
|
import { Prefix, Transformer } from '@airpower/transformer'
|
|
@@ -80,14 +213,19 @@ class User extends Transformer {
|
|
|
80
213
|
email!: string // JSON 中对应 'user_email'
|
|
81
214
|
}
|
|
82
215
|
|
|
83
|
-
const user = User.fromJson({
|
|
216
|
+
const user = User.fromJson({
|
|
217
|
+
user_id: 1,
|
|
218
|
+
user_name: 'John',
|
|
219
|
+
user_email: 'john@example.com'
|
|
220
|
+
})
|
|
221
|
+
|
|
84
222
|
console.log(user.id) // 输出: 1
|
|
85
223
|
console.log(user.name) // 输出: 'John'
|
|
86
224
|
```
|
|
87
225
|
|
|
88
|
-
|
|
226
|
+
### 2. `@Alias(alias: string)`
|
|
89
227
|
|
|
90
|
-
|
|
228
|
+
为字段设置别名,解决前后端字段命名规范不一致的问题。
|
|
91
229
|
|
|
92
230
|
```typescript
|
|
93
231
|
import { Alias, Transformer } from '@airpower/transformer'
|
|
@@ -102,14 +240,19 @@ class User extends Transformer {
|
|
|
102
240
|
email!: string // JSON 中对应 'user_email'
|
|
103
241
|
}
|
|
104
242
|
|
|
105
|
-
const user = User.fromJson({
|
|
243
|
+
const user = User.fromJson({
|
|
244
|
+
id: 1,
|
|
245
|
+
full_name: 'John Doe',
|
|
246
|
+
user_email: 'john@example.com'
|
|
247
|
+
})
|
|
248
|
+
|
|
106
249
|
console.log(user.name) // 输出: 'John Doe'
|
|
107
250
|
console.log(user.email) // 输出: 'john@example.com'
|
|
108
251
|
```
|
|
109
252
|
|
|
110
|
-
|
|
253
|
+
### 3. `@IgnorePrefix()`
|
|
111
254
|
|
|
112
|
-
|
|
255
|
+
让特定字段忽略类级别的前缀设置,适用于混合命名规范的场景。
|
|
113
256
|
|
|
114
257
|
```typescript
|
|
115
258
|
import { IgnorePrefix, Prefix, Transformer } from '@airpower/transformer'
|
|
@@ -122,14 +265,18 @@ class User extends Transformer {
|
|
|
122
265
|
temporaryId!: string // JSON 中对应 'temporaryId',不带前缀
|
|
123
266
|
}
|
|
124
267
|
|
|
125
|
-
const user = User.fromJson({
|
|
268
|
+
const user = User.fromJson({
|
|
269
|
+
api_id: 1,
|
|
270
|
+
temporaryId: 'temp123'
|
|
271
|
+
})
|
|
272
|
+
|
|
126
273
|
console.log(user.id) // 输出: 1
|
|
127
274
|
console.log(user.temporaryId) // 输出: 'temp123'
|
|
128
275
|
```
|
|
129
276
|
|
|
130
|
-
|
|
277
|
+
### 4. `@Type(constructor: Class, isArray: boolean)`
|
|
131
278
|
|
|
132
|
-
|
|
279
|
+
指定字段的类型,支持嵌套对象和数组的自动转换。
|
|
133
280
|
|
|
134
281
|
```typescript
|
|
135
282
|
import { Transformer, Type } from '@airpower/transformer'
|
|
@@ -154,7 +301,11 @@ class User extends Transformer {
|
|
|
154
301
|
const userData = {
|
|
155
302
|
id: 1,
|
|
156
303
|
name: 'John',
|
|
157
|
-
address: {
|
|
304
|
+
address: {
|
|
305
|
+
street: '123 Main St',
|
|
306
|
+
city: 'New York',
|
|
307
|
+
zipCode: '10001'
|
|
308
|
+
},
|
|
158
309
|
addresses: [
|
|
159
310
|
{ street: '456 Oak Ave', city: 'Boston', zipCode: '02101' },
|
|
160
311
|
{ street: '789 Pine Rd', city: 'Chicago', zipCode: '60601' }
|
|
@@ -167,12 +318,12 @@ console.log(user.addresses.length) // 输出: 2
|
|
|
167
318
|
console.log(user.addresses[0].city) // 输出: 'Boston'
|
|
168
319
|
```
|
|
169
320
|
|
|
170
|
-
|
|
321
|
+
### 5. `@ToClass(func: (json) => any)`
|
|
171
322
|
|
|
172
|
-
|
|
323
|
+
自定义从 JSON 到类实例的转换逻辑,适用于需要特殊处理的字段。
|
|
173
324
|
|
|
174
325
|
```typescript
|
|
175
|
-
import { ToClass,
|
|
326
|
+
import { ToClass, Transformer } from '@airpower/transformer'
|
|
176
327
|
|
|
177
328
|
class User extends Transformer {
|
|
178
329
|
id!: number
|
|
@@ -180,105 +331,72 @@ class User extends Transformer {
|
|
|
180
331
|
|
|
181
332
|
@ToClass(json => new Date(json.birthday_timestamp * 1000))
|
|
182
333
|
birthday!: Date
|
|
183
|
-
|
|
184
|
-
@ToJson(instance => Math.floor(instance.birthday.getTime() / 1000))
|
|
185
|
-
birthdayTimestamp!: number
|
|
186
334
|
}
|
|
187
335
|
|
|
188
336
|
const userData = {
|
|
189
337
|
id: 1,
|
|
190
338
|
name: 'John',
|
|
191
|
-
birthday_timestamp: 1609459200 // 2021-01-01
|
|
339
|
+
birthday_timestamp: 1609459200 // 2021-01-01 的时间戳
|
|
192
340
|
}
|
|
193
341
|
|
|
194
342
|
const user = User.fromJson(userData)
|
|
195
343
|
console.log(user.birthday) // 输出: Date 对象 (2021-01-01)
|
|
196
344
|
```
|
|
197
345
|
|
|
198
|
-
###
|
|
199
|
-
|
|
200
|
-
```typescript
|
|
201
|
-
import { Alias, IgnorePrefix, Prefix, Transformer, Type } from '@airpower/transformer'
|
|
346
|
+
### 6. `@ToJson(func: (instance) => any)`
|
|
202
347
|
|
|
203
|
-
|
|
204
|
-
@Prefix('addr_')
|
|
205
|
-
class Address extends Transformer {
|
|
206
|
-
id!: number
|
|
207
|
-
@Alias('street_address')
|
|
208
|
-
street!: string
|
|
348
|
+
自定义从类实例到 JSON 的转换逻辑,适用于需要特殊格式输出的字段。
|
|
209
349
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
350
|
+
```typescript
|
|
351
|
+
import { ToJson, Transformer } from '@airpower/transformer'
|
|
213
352
|
|
|
214
|
-
|
|
215
|
-
class Role extends Transformer {
|
|
353
|
+
class User extends Transformer {
|
|
216
354
|
id!: number
|
|
217
355
|
name!: string
|
|
218
|
-
|
|
219
|
-
|
|
356
|
+
birthday!: Date
|
|
357
|
+
|
|
358
|
+
@ToJson(instance => Math.floor(instance.birthday.getTime() / 1000))
|
|
359
|
+
birthdayTimestamp!: number
|
|
220
360
|
}
|
|
221
361
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
@Alias('full_name')
|
|
227
|
-
name!: string
|
|
362
|
+
const user = new User()
|
|
363
|
+
user.id = 1
|
|
364
|
+
user.name = 'John'
|
|
365
|
+
user.birthday = new Date('2021-01-01')
|
|
228
366
|
|
|
229
|
-
|
|
367
|
+
const json = user.toJson()
|
|
368
|
+
console.log(json.birthdayTimestamp) // 输出: 1609459200
|
|
369
|
+
```
|
|
230
370
|
|
|
231
|
-
|
|
232
|
-
temporaryToken!: string
|
|
371
|
+
---
|
|
233
372
|
|
|
234
|
-
|
|
235
|
-
homeAddress!: Address
|
|
373
|
+
## 📦 API 参考
|
|
236
374
|
|
|
237
|
-
|
|
238
|
-
roles: Role[] = []
|
|
375
|
+
### Transformer 类方法
|
|
239
376
|
|
|
240
|
-
|
|
241
|
-
|
|
377
|
+
| 方法 | 参数 | 返回值 | 描述 |
|
|
378
|
+
|-----------------------------|--------------------------------------|---------|-----------------------------|
|
|
379
|
+
| `fromJson(json)` | `json: IJson` | `T` | 从 JSON 对象创建类实例,自动进行数据别名转换 |
|
|
380
|
+
| `fromJsonArray(jsonArray)` | `jsonArray: IJson \| IJson[]` | `T[]` | 从 JSON 数组创建类实例数组 |
|
|
381
|
+
| `newInstance(Class, json?)` | `Class: Constructor`, `json?: IJson` | `T` | 创建类的新实例,可选择性地用 JSON 数据初始化 |
|
|
382
|
+
| `copy()` | - | `this` | 复制当前实例到新实例 |
|
|
383
|
+
| `expose(...fields)` | `fields: string[]` | `void` | 只保留指定的字段,其他字段设为 `undefined` |
|
|
384
|
+
| `exclude(...fields)` | `fields: string[]` | `void` | 排除指定的字段,将指定字段设为 `undefined` |
|
|
385
|
+
| `recoverBy(json)` | `json: IJson \| Transformer` | `void` | 用指定的 JSON 数据恢复/覆盖当前实例状态 |
|
|
386
|
+
| `toJson()` | - | `IJson` | 将实例转换为 JSON 对象,自动进行数据别名转换 |
|
|
242
387
|
|
|
243
|
-
|
|
244
|
-
const jsonData = {
|
|
245
|
-
usr_id: 1,
|
|
246
|
-
full_name: 'John Doe',
|
|
247
|
-
usr_email: 'john@example.com',
|
|
248
|
-
temporaryToken: 'abc123',
|
|
249
|
-
homeAddress: {
|
|
250
|
-
addr_id: 1,
|
|
251
|
-
street_address: '123 Main St',
|
|
252
|
-
addr_city: 'New York',
|
|
253
|
-
addr_country: 'USA'
|
|
254
|
-
},
|
|
255
|
-
roles: [
|
|
256
|
-
{
|
|
257
|
-
role_id: 1,
|
|
258
|
-
role_name: 'Admin',
|
|
259
|
-
permissions: ['read', 'write', 'delete']
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
role_id: 2,
|
|
263
|
-
role_name: 'User',
|
|
264
|
-
permissions: ['read']
|
|
265
|
-
}
|
|
266
|
-
],
|
|
267
|
-
usr_createdAt: '2023-01-01T00:00:00Z'
|
|
268
|
-
}
|
|
388
|
+
### 装饰器
|
|
269
389
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
390
|
+
| 装饰器 | 参数 | 作用目标 | 描述 |
|
|
391
|
+
|--------------------------|-------------------------------------------|------|-------------------|
|
|
392
|
+
| `@Prefix(prefix)` | `prefix: string` | 类 | 为类的所有字段设置统一前缀 |
|
|
393
|
+
| `@Alias(alias)` | `alias: string` | 字段 | 为字段设置别名 |
|
|
394
|
+
| `@IgnorePrefix()` | - | 字段 | 让字段忽略类级别的前缀 |
|
|
395
|
+
| `@Type(Class, isArray?)` | `Class: Constructor`, `isArray?: boolean` | 字段 | 指定字段的类型,支持嵌套对象和数组 |
|
|
396
|
+
| `@ToClass(func)` | `func: (json) => any` | 字段 | 自定义从 JSON 到类的转换逻辑 |
|
|
397
|
+
| `@ToJson(func)` | `func: (instance) => any` | 字段 | 自定义从类到 JSON 的转换逻辑 |
|
|
277
398
|
|
|
278
|
-
|
|
279
|
-
const jsonOutput = user.toJson()
|
|
280
|
-
console.log(JSON.stringify(jsonOutput, null, 2))
|
|
281
|
-
```
|
|
399
|
+
---
|
|
282
400
|
|
|
283
401
|
## 🚀 常见使用场景
|
|
284
402
|
|
|
@@ -286,53 +404,144 @@ console.log(JSON.stringify(jsonOutput, null, 2))
|
|
|
286
404
|
|
|
287
405
|
当后端 API 返回的数据格式与前端模型不匹配时,使用装饰器可以轻松完成数据转换。
|
|
288
406
|
|
|
407
|
+
```typescript
|
|
408
|
+
@Prefix('data_')
|
|
409
|
+
class ApiResponse extends Transformer {
|
|
410
|
+
@Type(User)
|
|
411
|
+
userInfo!: User
|
|
412
|
+
|
|
413
|
+
@Alias('status_code')
|
|
414
|
+
statusCode!: number
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
289
418
|
### 2. 数据验证和清洗
|
|
290
419
|
|
|
291
420
|
在数据进入应用之前,通过转换过程进行初步的验证和清洗。
|
|
292
421
|
|
|
422
|
+
```typescript
|
|
423
|
+
class User extends Transformer {
|
|
424
|
+
@ToClass(json => json.email?.toLowerCase().trim())
|
|
425
|
+
email!: string
|
|
426
|
+
|
|
427
|
+
@ToClass(json => json.phone?.replace(/\D/g, ''))
|
|
428
|
+
phone!: string
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
293
432
|
### 3. 不同系统间的数据交换
|
|
294
433
|
|
|
295
434
|
在微服务架构中,不同服务可能使用不同的数据格式,此库可以帮助统一数据格式。
|
|
296
435
|
|
|
436
|
+
```typescript
|
|
437
|
+
@Prefix('legacy_')
|
|
438
|
+
class LegacySystemData extends Transformer {
|
|
439
|
+
@Alias('USER_ID')
|
|
440
|
+
userId!: number
|
|
441
|
+
|
|
442
|
+
@Alias('USER_NAME')
|
|
443
|
+
userName!: string
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
297
447
|
### 4. 前后端数据格式差异
|
|
298
448
|
|
|
299
449
|
解决前端和后端开发团队使用不同命名约定的问题。
|
|
300
450
|
|
|
301
|
-
|
|
451
|
+
```typescript
|
|
452
|
+
// 后端使用 snake_case,前端使用 camelCase
|
|
453
|
+
@Prefix('user_')
|
|
454
|
+
class User extends Transformer {
|
|
455
|
+
@Alias('created_at')
|
|
456
|
+
createdAt!: Date
|
|
302
457
|
|
|
303
|
-
|
|
458
|
+
@Alias('updated_at')
|
|
459
|
+
updatedAt!: Date
|
|
460
|
+
}
|
|
461
|
+
```
|
|
304
462
|
|
|
305
|
-
|
|
306
|
-
|-----------------------------|---------------------------|
|
|
307
|
-
| `fromJson(json)` | 从 JSON 对象创建类实例 |
|
|
308
|
-
| `fromJsonArray(jsonArray)` | 从 JSON 数组创建类实例数组 |
|
|
309
|
-
| `newInstance(Class, json?)` | 创建类的新实例,可选择性地用 JSON 数据初始化 |
|
|
310
|
-
| `copy()` | 复制当前实例 |
|
|
311
|
-
| `expose(...fields)` | 只保留指定的字段 |
|
|
312
|
-
| `exclude(...fields)` | 排除指定的字段 |
|
|
313
|
-
| `recoverBy(json)` | 用 JSON 数据恢复实例状态 |
|
|
314
|
-
| `toJson()` | 将实例转换为 JSON |
|
|
463
|
+
### 5. 日期时间处理
|
|
315
464
|
|
|
316
|
-
|
|
465
|
+
处理不同系统间的日期时间格式转换。
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
class Event extends Transformer {
|
|
469
|
+
@ToClass(json => new Date(json.event_date))
|
|
470
|
+
eventDate!: Date
|
|
471
|
+
|
|
472
|
+
@ToJson(instance => instance.eventDate.toISOString())
|
|
473
|
+
eventDateIso!: string
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
## 🔧 开发指南
|
|
480
|
+
|
|
481
|
+
### 项目结构
|
|
482
|
+
|
|
483
|
+
```
|
|
484
|
+
src/
|
|
485
|
+
├── decorator/ # 装饰器实现
|
|
486
|
+
│ ├── Alias.ts # 字段别名装饰器
|
|
487
|
+
│ ├── IgnorePrefix.ts # 忽略前缀装饰器
|
|
488
|
+
│ ├── Prefix.ts # 类前缀装饰器
|
|
489
|
+
│ ├── ToClass.ts # 自定义类转换装饰器
|
|
490
|
+
│ ├── ToJson.ts # 自定义 JSON 转换装饰器
|
|
491
|
+
│ └── Type.ts # 类型转换装饰器
|
|
492
|
+
├── transformer/ # 核心转换器实现
|
|
493
|
+
│ ├── IJson.ts # JSON 接口定义
|
|
494
|
+
│ ├── ITransformerConstructor.ts # 构造函数接口
|
|
495
|
+
│ └── Transformer.ts # 主转换器类
|
|
496
|
+
├── type/ # 类型定义
|
|
497
|
+
│ └── index.ts # 类型导出
|
|
498
|
+
├── util/ # 工具类
|
|
499
|
+
│ └── DecoratorUtil.ts # 装饰器工具类
|
|
500
|
+
└── index.ts # 主入口文件
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### 构建命令
|
|
317
504
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
505
|
+
```bash
|
|
506
|
+
# 安装依赖
|
|
507
|
+
npm install
|
|
508
|
+
|
|
509
|
+
# 运行 ESLint 检查、TypeScript 编译和 Vite 打包
|
|
510
|
+
npm run build
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### 版本发布自动化流程
|
|
514
|
+
|
|
515
|
+
- 使用 `eslint --fix` 修复项目中可能出现的问题
|
|
516
|
+
- 更新 `package.json` 中的版本号
|
|
517
|
+
- 使用 `yarn build` 构建项目
|
|
518
|
+
- 使用 `npm publish` 发布包
|
|
519
|
+
- 使用 `git add/commit/push` 将本地所有变更的文件推送到 Github
|
|
520
|
+
- 根据当前版本创建 `git tag` 并推送到Github,格式例如 `v1.2.3`
|
|
521
|
+
|
|
522
|
+
---
|
|
326
523
|
|
|
327
524
|
## 🤝 贡献
|
|
328
525
|
|
|
329
526
|
欢迎提交 Issue 和 Pull Request 来帮助改进这个项目!
|
|
330
527
|
|
|
528
|
+
### 贡献步骤
|
|
529
|
+
|
|
530
|
+
1. Fork 本仓库
|
|
531
|
+
2. 创建你的特性分支 (`git checkout -b feature/AmazingFeature`)
|
|
532
|
+
3. 提交你的更改 (`git commit -m 'Add some AmazingFeature'`)
|
|
533
|
+
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
|
534
|
+
5. 开启一个 Pull Request
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
331
538
|
## ⏰ 支持与反馈
|
|
332
539
|
|
|
333
|
-
|
|
540
|
+
- 📝 **问题反馈**:通过本仓库的 [Issues](https://github.com/AirPowerTeam/AirPower-Transformer/issues) 与我们联系
|
|
541
|
+
- 💡 **需求建议**:欢迎通过本仓库的 [Issues](https://github.com/AirPowerTeam/AirPower-Transformer/issues) 提出
|
|
542
|
+
- 💬 **技术交流**:加入 QQ 群 **555156313** 与我们及时反馈
|
|
334
543
|
|
|
335
|
-
|
|
544
|
+
---
|
|
336
545
|
|
|
337
546
|
## 📄 许可证
|
|
338
547
|
|
|
@@ -340,8 +549,17 @@ MIT License
|
|
|
340
549
|
|
|
341
550
|
---
|
|
342
551
|
|
|
552
|
+
## 👥 团队信息
|
|
553
|
+
|
|
554
|
+
- **作者**:Hamm
|
|
555
|
+
- **邮箱**:admin@hamm.cn
|
|
556
|
+
- **Github**:[HammCn](https://github.com/HammCn)
|
|
557
|
+
- **团队**:[AirPowerTeam](https://github.com/AirPowerTeam)
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
343
561
|
<p align="center">
|
|
344
|
-
<a href="https://github.com/AirPowerTeam/AirPower-Transformer">Github</a>
|
|
345
|
-
<a href="https://gitee.com/air-power/AirPower-Transformer">Gitee</a>
|
|
562
|
+
<a href="https://github.com/AirPowerTeam/AirPower-Transformer">Github</a> ·
|
|
563
|
+
<a href="https://gitee.com/air-power/AirPower-Transformer">Gitee</a> ·
|
|
346
564
|
<a href="https://www.npmjs.com/package/@airpower/transformer">NPM</a>
|
|
347
565
|
</p>
|