import { isString, isObject, isNumber, isNull, isInteger, isEmpty, isBoolean } from 'lodash-es'
|
const isArray = Array.isArray
|
|
class Convert {
|
constructor() {
|
this._option = {
|
$id: 'http://example.com/root.json',
|
$schema: 'http://json-schema.org/draft-07/schema#'
|
}
|
this._object = null
|
}
|
|
/**
|
* 转换函数
|
* @param {*} object 需要转换的对象
|
* @param {*} ?option 可选参数,目前只有能设置 root 节点的 $id 和 $schema
|
*/
|
format(object, option = {}) {
|
// 数据校验,确保传入的的object只能是对象或数组
|
if (!isObject(object)) {
|
throw new TypeError('传入参数只能是对象或数组')
|
}
|
// 合并属性
|
this._option = Object.assign(this._option, option)
|
// 需要转换的对象
|
this._object = object
|
let convertRes
|
// 数组类型和对象类型结构不一样
|
if (isArray(object)) {
|
convertRes = this._arrayToSchema()
|
} else {
|
convertRes = this._objectToSchema()
|
}
|
// 释放
|
this._object = null
|
return convertRes
|
}
|
|
/**
|
* 数组类型转换成JSONSCHEMA
|
*/
|
_arrayToSchema() {
|
// root节点基本信息
|
const result = this._value2object(this._object, this._option.$id, '', true)
|
if (this._object.length > 0) {
|
const itemArr = []
|
for (let index = 0; index < this._object.length; index++) {
|
// 创建items对象的基本信息
|
const objectItem = this._object[index]
|
let item = this._value2object(objectItem, `#/items`, 'items')
|
if (isObject(objectItem) && !isEmpty(objectItem)) {
|
// 递归遍历
|
const objectItemSchema = this._json2schema(objectItem, `#/items`)
|
// 合并对象
|
item = Object.assign(item, objectItemSchema)
|
}
|
itemArr.push(item)
|
}
|
result['items'] = itemArr
|
}
|
return result
|
}
|
|
/**
|
* 对象类型转换成JSONSCHEMA
|
*/
|
_objectToSchema() {
|
let baseResult = this._value2object(this._object, this._option.$id, '', true)
|
const objectSchema = this._json2schema(this._object)
|
baseResult = Object.assign(baseResult, objectSchema)
|
return baseResult
|
}
|
|
_json2schema(object, name = '') {
|
// 如果递归值不是对象,那么return掉
|
if (!isObject(object)) {
|
return
|
}
|
// 处理当前路径$id
|
if (name === '' || name === undefined) {
|
name = '#'
|
}
|
const result = {}
|
// 判断传入object是对象还是数组。
|
if (isArray(object)) {
|
result.items = {}
|
} else {
|
result.properties = {}
|
}
|
// 遍历传入的对象
|
for (const key in object) {
|
if (Object.prototype.hasOwnProperty.call(object, key)) {
|
const element = object[key]
|
// 如果只是undefined。跳过
|
if (element === undefined) {
|
continue
|
}
|
const $id = `${name}/properties/${key}`
|
// 判断当前 element 的值 是否也是对象,如果是就继续递归,不是就赋值给result
|
if (!result['properties']) {
|
continue
|
}
|
if (isObject(element)) {
|
// 创建当前属性的基本信息
|
result['properties'][key] = this._value2object(element, $id, key)
|
if (isArray(element)) {
|
// 针对空数组和有值的数组做不同处理
|
if (element.length > 0) {
|
// 是数组
|
const itemArr = []
|
for (let index = 0; index < element.length; index++) {
|
const elementItem = element[index]
|
// 创建items对象的基本信息
|
let item = this._value2object(elementItem, `${$id}/items`, key + 'items')
|
// 判断第一项是否是对象,且对象属性不为空
|
if (isObject(elementItem) && !isEmpty(elementItem)) {
|
// 新增的properties才合并进来
|
item = Object.assign(item, this._json2schema(elementItem, `${$id}/items`))
|
}
|
itemArr.push(item)
|
}
|
result['properties'][key]['items'] = itemArr
|
}
|
} else {
|
// 不是数组,递归遍历获取,然后合并对象属性
|
result['properties'][key] = Object.assign(
|
result['properties'][key],
|
this._json2schema(element, $id)
|
)
|
}
|
} else {
|
// 一般属性直接获取基本信息
|
if (result['properties']) {
|
result['properties'][key] = this._value2object(element, $id, key)
|
}
|
}
|
}
|
}
|
return result
|
}
|
|
/**
|
* 把json的值转换成对象类型
|
* @param {*} value
|
* @param {*} $id
|
* @param {*} key
|
*/
|
_value2object(value, $id, key = '', root = false) {
|
const objectTemplate = {
|
$id: $id,
|
title: `The ${key} Schema`,
|
mock: {
|
mock: value
|
}
|
}
|
|
// 判断是否为初始化root数据
|
if (root) {
|
objectTemplate['$schema'] = this._option.$schema
|
objectTemplate['title'] = `The Root Schema`
|
objectTemplate['mock'] = undefined
|
}
|
if (isBoolean(value)) {
|
objectTemplate.type = 'boolean'
|
} else if (isInteger(value)) {
|
objectTemplate.type = 'integer'
|
} else if (isNumber(value)) {
|
objectTemplate.type = 'number'
|
} else if (isString(value)) {
|
objectTemplate.type = 'string'
|
} else if (isNull(value)) {
|
objectTemplate.type = 'null'
|
} else if (isArray(value)) {
|
objectTemplate.type = 'array'
|
objectTemplate['mock'] = undefined
|
} else if (isObject(value)) {
|
objectTemplate.type = 'object'
|
objectTemplate['mock'] = undefined
|
}
|
|
return objectTemplate
|
}
|
}
|
export default Convert
|