This repository has been archived by the owner on Jun 10, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from typed-project/converter
Converter
- Loading branch information
Showing
20 changed files
with
768 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
|
||
export interface ConvertServiceOptions { | ||
|
||
returnType?: Function; | ||
|
||
customConverter?: Function|Function[]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
|
||
export class ConverterMetadata { | ||
|
||
private _type: Function; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import {IConverter} from "./interface/IConverter"; | ||
|
||
export class ConverterRegistry { | ||
|
||
private static _converters: Map<Function, IConverter> = new Map(); | ||
|
||
public static registerConverter(type: Function, converter: IConverter) { | ||
this._converters.set(type, converter); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import {Service} from "../mvc/decorator/Service"; | ||
import {PropertyRegistry} from "./PropertyRegistry"; | ||
import {PropertyMetadata} from "./PropertyMetadata"; | ||
import * as _ from "lodash"; | ||
import {TypeUtil} from "../util/TypeUtil"; | ||
import {Klass} from "../core/Klass"; | ||
|
||
/** | ||
* ConverterService used to convert class to object and vice-versa. | ||
*/ | ||
@Service() | ||
export class ConverterService { | ||
|
||
public convert(data: any, returnType: Function, baseType?: Function) { | ||
|
||
const type = data.constructor; | ||
let properties; | ||
|
||
if (returnType === type && typeof baseType === 'undefined') { | ||
return data; | ||
} | ||
|
||
if (_.isUndefined(data) || _.isNull(data)) { | ||
return data; | ||
} | ||
|
||
if (returnType === String) { | ||
return "" + data; | ||
} | ||
|
||
if (returnType === Number) { | ||
return +data; | ||
} | ||
|
||
if (returnType === Boolean) { | ||
if (data === 'true') return true; | ||
if (data === 'false') return false; | ||
|
||
return !!data; | ||
} | ||
|
||
if (returnType === Date) { | ||
return new Date(data); | ||
} | ||
|
||
if (returnType === Array && type === Array && baseType) { | ||
return data.map(item => this.convert(item, baseType)); | ||
} | ||
|
||
if (returnType === Map && type === Map && baseType) { | ||
const result = new Map(); | ||
|
||
data.forEach((value, key) => { | ||
result.set(key, this.convert(value, baseType)); | ||
}); | ||
|
||
return result; | ||
} | ||
|
||
/* | ||
* | ||
* Convert class instance to object | ||
* If provide a converter, and implement serialize function | ||
* it will use serialize function result as the property value | ||
* | ||
*/ | ||
|
||
properties = PropertyRegistry.properties.get(type); | ||
if (returnType === Object && !TypeUtil.isSimpleType(type) && properties) { | ||
|
||
const result = {}; | ||
|
||
properties.forEach((metadata: PropertyMetadata) => { | ||
let value = data[metadata.klassProperty]; | ||
|
||
value = this.convert(value, metadata.propertyType, metadata.baseType); | ||
|
||
if (metadata.converter && metadata.converter.serialize) { | ||
value = metadata.converter.serialize(data, metadata.klassProperty, metadata.objectProperty); | ||
} | ||
|
||
result[metadata.objectProperty] = value; | ||
}); | ||
|
||
return result; | ||
} | ||
|
||
/* | ||
* | ||
* Convert object to class instance | ||
* If provide a converter, and implement deserialize function | ||
* it will use deserialize function result as the property value | ||
* | ||
*/ | ||
properties = PropertyRegistry.properties.get(returnType); | ||
if (type === Object && !TypeUtil.isSimpleType(returnType) && properties) { | ||
|
||
const klass = <Klass> returnType; | ||
const ins = new klass(); | ||
|
||
properties.forEach((metadata: PropertyMetadata) => { | ||
let value = data[metadata.objectProperty]; | ||
|
||
value = this.convert(value, metadata.propertyType, metadata.baseType); | ||
|
||
if (metadata.converter && metadata.converter.deserialize) { | ||
value = metadata.converter.deserialize(data, metadata.klassProperty, metadata.objectProperty); | ||
} | ||
|
||
ins[metadata.klassProperty] = value; | ||
}); | ||
|
||
return ins; | ||
} | ||
|
||
throw new Error(`not support convert data`); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import {IConverter} from "./interface/IConverter"; | ||
|
||
export class PropertyMetadata { | ||
|
||
private _type: Function; | ||
|
||
private _klassProperty: string; | ||
|
||
private _objectProperty: string; | ||
|
||
private _propertyType: Function; | ||
|
||
private _converter: IConverter; | ||
|
||
private _baseType: Function; | ||
|
||
get type(): Function { | ||
return this._type; | ||
} | ||
|
||
get objectProperty(): string { | ||
return this._objectProperty; | ||
} | ||
|
||
get klassProperty(): string { | ||
return this._klassProperty; | ||
} | ||
|
||
get propertyType(): Function { | ||
return this._propertyType; | ||
} | ||
|
||
get converter(): IConverter { | ||
return this._converter; | ||
} | ||
|
||
set converter(value: IConverter) { | ||
this._converter = value; | ||
} | ||
|
||
get baseType(): Function { | ||
return this._baseType; | ||
} | ||
|
||
set baseType(value: Function) { | ||
this._baseType = value; | ||
} | ||
|
||
constructor(type: Function, klassProperty: string, objectProperty: string, propertyType: Function) { | ||
this._type = type; | ||
this._objectProperty = objectProperty; | ||
this._klassProperty = klassProperty; | ||
this._propertyType = propertyType; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import {IConverter} from "./interface/IConverter"; | ||
|
||
export interface PropertyOptions { | ||
|
||
name?: string; | ||
|
||
converter?: IConverter; | ||
|
||
baseType?: Function; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import {PropertyMetadata} from "./PropertyMetadata"; | ||
import {PropertyOptions} from "./PropertyOptions"; | ||
import {Reflection} from "../core/Reflection"; | ||
import * as _ from 'lodash'; | ||
|
||
export class PropertyRegistry { | ||
|
||
public static properties: Map<Function, PropertyMetadata[]> = new Map(); | ||
|
||
|
||
public static registerObjectProperty(type: Function, klassProperty: string, nameOrOptions?: string|PropertyOptions) { | ||
const properties = this.findProperties(type); | ||
|
||
const propertyType = Reflection.getType(type.prototype, klassProperty); | ||
|
||
let objectProperty = klassProperty; | ||
let converter; | ||
let baseType; | ||
|
||
if (typeof nameOrOptions !== 'undefined') { | ||
|
||
if (_.isString(nameOrOptions)) { | ||
|
||
objectProperty = nameOrOptions; | ||
|
||
} else { | ||
|
||
const options = <PropertyOptions> nameOrOptions; | ||
|
||
if (typeof options.name !== 'undefined') { | ||
objectProperty = options.name; | ||
} | ||
|
||
if (typeof options.converter !== 'undefined') { | ||
converter = options.converter; | ||
} | ||
|
||
if (typeof options.baseType !== 'undefined') { | ||
baseType = options.baseType; | ||
} | ||
|
||
} | ||
} | ||
|
||
const propertyMetadata = new PropertyMetadata(type, klassProperty, objectProperty, propertyType); | ||
|
||
if (converter) { | ||
propertyMetadata.converter = converter; | ||
} | ||
|
||
if (baseType) { | ||
propertyMetadata.baseType = baseType; | ||
} | ||
|
||
properties.push(propertyMetadata); | ||
} | ||
|
||
public static findProperties(type: Function) { | ||
let properties = this.properties.get(type); | ||
|
||
if (typeof properties === 'undefined') { | ||
properties = []; | ||
this.properties.set(type, properties); | ||
} | ||
|
||
return properties; | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import {PropertyRegistry} from "../PropertyRegistry"; | ||
import {PropertyOptions} from "../PropertyOptions"; | ||
|
||
export function ObjectProperty(nameOrOptions?: string|PropertyOptions) { | ||
|
||
return (target: any, propertyName: string) => { | ||
|
||
PropertyRegistry.registerObjectProperty(target.constructor, propertyName, nameOrOptions); | ||
|
||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
|
||
export interface IConverter { | ||
|
||
serialize?(data: any, klassProperty: string, objectProperty: string): any; | ||
|
||
deserialize?(data: any, klassProperty: string, objectProperty: string): any; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.