Skip to content

Commit

Permalink
feat: json to basic schema (#450)
Browse files Browse the repository at this point in the history
  • Loading branch information
welkang authored and janryWang committed Dec 3, 2019
1 parent 4b6a9c0 commit 785a760
Show file tree
Hide file tree
Showing 3 changed files with 253 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"test": "npm run lint && jest",
"test:core": "jest --watch packages/core/src/__tests__/*.spec.ts",
"test:hook": "jest --watch packages/react/src/__tests__/*.spec.tsx",
"test:editor": "jest --watch packages/react-schema-editor/src/__tests__/*.spec.ts",
"test:prod": "cross-env TEST_ENV=production npm run build && jest",
"doc:core": "doc-scripts start -i packages/core",
"doc:react": "doc-scripts start -i packages/react",
Expand Down
156 changes: 156 additions & 0 deletions packages/react-schema-editor/src/__tests__/index.spec.ts
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)
})
})
96 changes: 96 additions & 0 deletions packages/react-schema-editor/src/utils/json2schema.ts
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'
}

0 comments on commit 785a760

Please sign in to comment.