-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
253 additions
and
0 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
156 changes: 156 additions & 0 deletions
156
packages/react-schema-editor/src/__tests__/index.spec.ts
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,156 @@ | ||
import { json2schema } from '../utils/json2schema' | ||
|
||
// mock datasource | ||
const testValues = { | ||
string: 'input test', | ||
boolean: true, | ||
checkbox: ['1'], | ||
date: '2019-12-12', | ||
daterange: ['2019-12-12', '2019-12-13'], | ||
number: 1, | ||
radio: '2', | ||
rating: 4, | ||
select: '1', | ||
textarea: 'test text', | ||
time: '00:00:04', | ||
transfer: [1, 2], | ||
year: '2013-01-01 00:00:00' | ||
} | ||
|
||
describe('json object transform', () => { | ||
test('values', () => { | ||
const result = json2schema(testValues) | ||
const validResult = { | ||
title: '', | ||
type: 'object', | ||
properties: [ | ||
{ | ||
title: '', | ||
type: 'string', | ||
example: 'input test', | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
{ | ||
title: '', | ||
type: 'boolean', | ||
example: true, | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
{ | ||
title: '', | ||
type: 'array', | ||
items: { | ||
title: '', | ||
type: 'string', | ||
example: '1', | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
{ | ||
title: '', | ||
type: 'string', | ||
example: '2019-12-12', | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
{ | ||
title: '', | ||
type: 'array', | ||
items: { | ||
title: '', | ||
type: 'string', | ||
example: '2019-12-12', | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
{ | ||
title: '', | ||
type: 'number', | ||
example: 1, | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
{ | ||
title: '', | ||
type: 'string', | ||
example: '2', | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
{ | ||
title: '', | ||
type: 'number', | ||
example: 4, | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
{ | ||
title: '', | ||
type: 'string', | ||
example: '1', | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
{ | ||
title: '', | ||
type: 'string', | ||
example: 'test text', | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
{ | ||
title: '', | ||
type: 'string', | ||
example: '00:00:04', | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
{ | ||
title: '', | ||
type: 'array', | ||
items: { | ||
title: '', | ||
type: 'number', | ||
example: 1, | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
description: '', | ||
'x-component': 'Input' | ||
}, | ||
{ | ||
title: '', | ||
type: 'string', | ||
example: '2013-01-01 00:00:00', | ||
enum: [], | ||
description: '', | ||
'x-component': 'Input' | ||
} | ||
], | ||
description: '' | ||
} | ||
|
||
// console.log(JSON.stringify(result, null, 2)) | ||
expect(result).toEqual(validResult) | ||
}) | ||
}) |
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,96 @@ | ||
/** | ||
* JSON 转换为 Schema | ||
* @param json | ||
* @param parentsPath | ||
*/ | ||
export function json2schema(json: any, parentsPath?: string) { | ||
let schema: any | ||
const newParentsPath = parentsPath || 'root' | ||
const type = getType(json) | ||
const component = getBasicComponent(type) | ||
|
||
if (type === 'object') { | ||
schema = schema || { | ||
title: '', | ||
type, | ||
properties: Object.keys(json).map(key => | ||
json2schema(json[key], newParentsPath + '.' + key) | ||
), | ||
description: '' | ||
} | ||
} else if (type === 'array') { | ||
schema = schema || { | ||
title: '', | ||
type, | ||
items: | ||
json.length <= 0 ? null : json2schema(json[0], newParentsPath + '[0]'), | ||
description: '', | ||
'x-component': component | ||
} | ||
} else { | ||
schema = { | ||
title: '', | ||
type, | ||
example: json, | ||
enum: [], | ||
description: '', | ||
'x-component': component | ||
} | ||
} | ||
|
||
return schema | ||
} | ||
|
||
function isPlainObject(obj: any) { | ||
return obj | ||
? typeof obj === 'object' && Object.getPrototypeOf(obj) === Object.prototype | ||
: false | ||
} | ||
|
||
/** | ||
* 获取值类型 | ||
* @param data | ||
*/ | ||
function getType(data: any) { | ||
let type = '' | ||
|
||
if (isPlainObject(data)) { | ||
type = 'object' | ||
} | ||
|
||
if (Array.isArray(data)) { | ||
type = 'array' | ||
} | ||
|
||
return type || typeof data | ||
} | ||
|
||
/** | ||
* 根据数据推算出对应的组件类型 | ||
* 策略: | ||
* 1. 如果是数组类型,如果子元素是一个对象,则更有可能是重复组件 | ||
* 2. 默认是 Input 输入框 | ||
* 3. Object 类型不处理 | ||
* 4. 如果文本超过 40 个字,默认推导为 textArea | ||
* @param data | ||
*/ | ||
function getBasicComponent(data: any) { | ||
const type = getType(data) | ||
const typeMap = { | ||
string: 'Input', | ||
number: 'Number', | ||
boolean: 'Switch', | ||
array: 'CardList' | ||
} | ||
|
||
let component = '' | ||
if (type === 'array') { | ||
component = getType(data[0]) === 'object' ? 'CardList' : 'Checkbox' | ||
} else if (type === 'string' && type.length >= 40) { | ||
component = 'TextArea' | ||
} else { | ||
component = typeMap[type] | ||
} | ||
|
||
return component || 'Input' | ||
} |