@shushu.pro/adapter
TypeScript icon, indicating that this package has built-in type declarations

0.1.0 • Public • Published

@shushu.pro/adapter

简介

adapter是一个简单,高效以声明的方式批量适配处理数据的工具,它能帮你对数据进行各种常见的适配转换,使得转换后的数据结构或者数据格式符合业务要求

adapter可以进行高度灵活的自定义扩展,来满足具体的业务需要,通过扩展生成各种速写指令来达到数据的快速处理,并保持数据处理的一致性和准确性

安装使用

yarn add @shushu.pro/adapter

简单示例

const data = {
    user: '张三',
    sex: 0,
    age: '18',
    books: [
        { name: '水浒传', type: 'm1', price: 50 },
        { name: '西游记', type: 'm2', price: 60 },
        { name: '三国演义', type: 'm3', price: null },
    ],
    address: ['浙江省', '杭州市', '江干区', '火车东站旁'],
}
const nextData = adapter({
    user: 'name',
    sex: { $enum: ['先生', '女士', '保密'] },
    age: Number,
    books: {
        name: true,
        type: { $emap: { m1: '武侠小说', m2: '神话小说', m3: '历史小说' } },
        price: { $default: '未知', $value: (value) => '¥' + value.toFixed(2) },
    },
    address: (value) => value.join(''),
}, data)

// 输出新数据
{
    name: '张三',
    sex: '先生',
    age: 18,
    books: [
        { name: '水浒传', type: '武侠小说', price: '¥50.00' },
        { name: '西游记', type: '神话小说', price: '¥60.00' },
        { name: '三国演义', type: '历史小说', price: '未知' },
    ],
    address: '浙江省杭州市江干区火车东站旁',
}

API指令集

模式指令

  • $strict 适配器严格模式,默认true
  • $clears 清除模式,默认false,清除提交请求参数特别有效

$strict 指令示例

严格模式

严格模式会对字段和适配器进行一一对应,适配器中未声明的字段将自动过滤

const testData = { key1:1, key2:1, key3:1 }
const newData = adapter({
    key1: true
}, testData)

// 输出 newData === { key1:1 }
非严格模式

非严格模式会拷贝所有未在适配器中定义的原始字段

const testData = { key1:1, key2:1, key3:1 }
const newData = adapter({
    $strict: false,
    key1: () => 666
}, testData)

// 输出 newData === { key1:666, key2:1, key3:1 }

$clears 指令示例

$clears指令可以控制过滤符合条件的字段,比如值为nullundefined,空字符串等字段

$clears设置为true时,则默认采用[null, undefined, '']规则进行过滤 当传入的是参数函数,filter(value, key, context),过滤返回值为true的项,参数:value(项的值),key(项的键),context(上下文环境)

const testData = { key1:'', key2:undefined, key3:null, key4:false, key5:555, key6:666,key7:true}

const newData1 = adapter({
    $strict: false,
    $clears: true
}, testData)
// 输出 newData1 === { key4:false, key4:false, key5:555, key6:666, key7:true }

const newData2 = adapter({
    $strict: false,
    $clears: ['null', 555, (val, key)=> val === 666 || key === 'key7']
}) 
// 输出 newData2 === {key1:'', key2:undefined, key4:false}

转换指令

  • $key 字段键名转换,默认不转换
  • $type 数据类型转换,使用JS内置转换规则
  • $enum 数据枚举类型转换
  • $emap 数据映射类型转换
  • $format 数据格式化转换
  • $value 数据值转换
  • $default 数据默认值设置
  • $filter 数组扩展指令

高级指令

  • $increase 数据添加层级
  • $reduce 数据缩减层级

字段衍生

可以将一个字段衍生出多个不同的字段,只要使用数组方式传递,例如:[ { $key:'value1', type:Boolean, }, { $key:'value2', type:Number } ] 将会使用原字段生成2个字段,分别是value1, value2,转换规则调用类型转换

运行上下

所有function类型的适配规则,都有一个上下文环境变量ctx,比如$value(value, ctx)$default(ctx)

const testData = {
    type: 3,
    data: {
        books: [
            {name:'水浒传'},
            {name:'西游记'}
        ]
    }
}

const newData = adapter({
    data:{
        books: {
            name: (value, { row, index, root }){
                // row 返回 项{name:'...'}
                // index 返回 项的下标
                // root 返回 根数据testData
                return `${index}.${value}`
            }
        }
    }
})

// 输出 newData === { data:{ books: [ {name:'0.水浒传'}, {name:'1.西游记'} ] } }

API方法

调用方法

  • adapter(setting) 初始化一个适配器对象
  • adapter(setting, data) 快速生成并调用适配器处理数据

扩展指令

  • adapter.addFormat(name, value) 添加一个预设format指令,name可以在$format指令中直接使用
  • adapter.addEnum(name, value) 添加一个预设的enumname可以在$enum指令中直接使用
  • adapter.addEmap(name, value) 添加一个预设的emapname可以在$emap指令中直接使用

通过传入对象形式的参数来批量添加扩展指令,例如:addEnum({ provinces:['浙江省', '江苏省'], citys: ['杭州', '宁波'] })

使用示例

键名转换 $key

const testData = { key1:1, key2:2, key3:3 }
const newData = adapter({
    key1: 'newKey1', // 使用速写指令进行转换
    key2: { $key: 'newKey2' } // 使用`$key`指令进行转换
    key3: { $key: (value) => 'newKey3'} // 使用函数
}, testData)

// 输出
{ newKey1:1, newKey2:2, newKey3:3 }

数据类型转换 $type

const testData = { toBoolean: 1, toNumber: '12', toString: 12, toDate: 1561750773712, value: 1 }
const newData = adapter({
    toBoolean: Boolean,
    toNumber: Number,
    toString: String, 
    toDate: Date,
    value1: 'type:Boolean',
    value: [ // 衍生字段
        'key:value2 type:Boolean', // 速写指令 
        { $key: 'value3', type:String }, // 对象型指令
    ]
})

// 输出,使用JS内置转换规则
{ toBoolean:true, toNumber:12, toString:'12', toDate: new Date(1561750773712), value1:true, value2:true, value3:'1' }

枚举转换 $enum

const testData = { type:1 }
const newData = adapter({
    type1: 'enmu:中国,美国'
    type: [
        'key:type2 enmu:中国,美国', // 速写指令
        { $key:'type3', $enmu:['中国', '美国'] }
    ],
    
}, testData)

// 输出
{ type1:'美国', type2:'美国', type3:'美国' }

扩展预设枚举转换 adapter.addEnmu(...) + $enum

adapter.addEnum({ // 扩展的枚举,在指令中可以直接使用名字去索引,对于一些公用的枚举进行统一管理维护,使用速写方式快速的对数据进行转换
    country: ['中国', '美国'],
    province: ['北京市', '杭州市']
})

const testData = { country:0, province:1 }
const newData = adapter({
    country: 'enum:country',
    province: {$enum:'province'}
}, testData)

// 输出
{country:'中国', province:'杭州市'}

映射转换 $emap

同枚举转换,区别在于一个是数字类型的参数来查询数组数据,一个是键的方式查询对象的值

扩展格式化指令 adapter.addFormat(...) + $format

格式化指令是一个很强大的设定,你可以定义任意的格式化指令,然后在需要使用的地方使用,一个适配规则可以使用任意多次,任意顺序的格式化指令

 adapter.addFormat('increase', (value, ctx, num = 1) => { // 一个累加器,可以给一个值进行累加操作
    return value + Number(num)
})
adapter.addFormat('toArray', (value, ctx, token = ',') => { // 转换数组
    return value.split(token)
})
adapter.addFormat('toMap', (value, ctx, arr) => { // 转换数组为map
    const map = {}
    arr.forEach(key => {
        map[key] = key
    })
    return map
})

const testData = { value: 1, value2: 2 }
const newData = adapter({
    value: {  // 传递多条指令,就像管道函数一样,前面的结果作为后面的输入
        $format: ['increase:1', 'increase:-2', 'increase:1234', (value) => String(value), 'toArray:'],
    },
    value2: [ // 传递任意多个,任意类型的参数
        { $key: 'nameMap', $format: { name: 'toMap', args:[ ['张三', '李四'] ] } },
        { $key: 'numMap', $format: { name: 'toMap', args:[ [1, 2] ] } },
    ]
}, testData)

// 输出
{ 
    value: ['1', '2', '3', '4'], 
    nameMap: {'张三':'张三', '李四':'李四'},
    numMap: {'1':'1', '2':'2'}
}

$format数组模式下,允许使用{$enum:'enumName'}, {$emap:'emapName'}进行枚举和映射转化,或者{$enum:[...]},{$emap:{...}}

使用值进行转换 $value

const testData = { value: 1, data: { name:'张三' } }
const newData = adapter({
    value: (value, ctx) => value + 'K',
    data: (value,) => value.name
}, testData)

// 输出
{ value: '1K', data: '张三'}

使用默认值

const testData = { 
    list: [
        { name: null, data: null, age: undefined },
        { name: '张三', data: ['中国', '美国'], age:12 }
    ]
}
const newData = adapter({
    list: {
        name: 'default:保密',
        data: { $default:() => ['中国'] },
        age: { $default:16 }
    }
}, testData)

// 输出
{
    list: [
        { name:'保密', data:['中国'], age:16 },
        { name:'张三', data:['中国', '美国'], age:12 }
    ]
}

数组过滤指令 $filter

const data = {
  list: [
    { id: 1, value: 1 },
    { id: 2, value: 2 },
    { id: 3, value: 3 },
    { id: 4, value: 4 },
    { id: 5, value: 5 },
    { id: 6, value: 6 },
  ],
}
const nextData = adapter({
  list: {
    $filter: (value) => value.id % 2 === 0 || value.value === 5,
    id: {
      $key: 'name',
      $type: String,
    },
  },
}, data)

// 输出
{
    list: [
        { name:'2' },
        { name:'4' },
        { name:'5' },
        { name:'6' },
    ]
}

扩展层级 $increase

const testData = { data:{ name:'张三' } }
const newData = adapter({
    data: {
        $key: 'name',
        $value: (value) => value.name,
    },
    $increase:{ // 扩展了data1字段
        $key: 'data1',
        $increase: {
            $key:'data2', // 扩展了data2字段
            data: {
                $key: 'name2',
                 $value: (value) => value.name
            }
        },
        data: {
            $key: 'name1',
            $value: (value) => value.name
        },
    }
}, testData)

// 输出
{
    name: '张三',
    data1: {
        name1: '张三',
        data2: {
            name2: '张三'
        }
    }
}

扩展字段使用当前层级的数据进行扩展,一般用在数据进行模块化拆分的时候使用

缩减字段 $reduce

const testData = {
    data1: {
        data2: {
            name2: '张三'
        }
    }
}
const newData = adapter({
    data1: { // 缩减data1
        $reduce: true,
        data2: {
            $reduce: true,
            name2: 'name'
        }
    }
}, testData)

// 输出 { name:'张三' }

// 缩减层级,一般在去除模块化实现字段扁平化的时候使用,比如前端业务得到的数据是模块化的,提交给网关需要扁平化,则使用此指令方便数据处理

简单的使用示例

import adapter from '@shushu.pro/adapter'

adapter.addFormat('dateDefault', (value, format) => { // 添加预设的格式化规则,后期可以快速调用
    value = new Date(value)
    if (format === 'YYYY') {
        return value.getFullYear()
    }
    return value.getFullYear() + '/' + (value.getMonth() + 1) + '/' + value.getDate()
})

const originData = {
    data1: [
        {
            goodsCode: 'SP10001',
            goodsTitle: '一件神奇的衣服',
            price: 1.2,
            goodsType: 'normal',
            goodsStatus: 1,
            goodsSkuList: [
                {
                    id: 1000,
                    attrs: ['红色', 'XXL'],
                },
                {
                    id: 1001,
                    attrs: ['黑色', 'XXL'],
                },
            ],
            isSale: 1,
            createTime: 1561750763712,
            modifyTime: null,
        },
        {
            goodsCode: 'SP10002',
            goodsTitle: '一条神奇的裤子',
            price: 2.2,
            goodsType: 'virtual',
            goodsStatus: 2,
            goodsSkuList: [
                {
                    id: 1000,
                    attrs: ['红色', 'XXL'],
                },
                {
                    id: 1001,
                    attrs: ['黑色', 'XXL'],
                },
            ],
            isSale: 0,
            createTime: 1561750773712,
            modifyTime: 1561750773712,
        },
    ],
    discardField1: null,
    discardField2: null,
    provinces: '中国,美国,日本',
}

const newData = adapter({
    data1: {
        $key: 'list', // 重命名data1 => list
        goodsCode: 'code', // 重命名goodsCode => code
        goodsTitle: {
            $key: 'title',
            $value: (value) => '标题:' + value, // 进行重命名和数据格式化,可以通过扩展来生成速写指令`key:title #prepend:标题:`
        },
        price: (value) => '¥' + value.toFixed(2), // 进行数据格式
        goodsType: { $emap: { normal: '常规商品', virtual: '虚拟商品' } }, // 进行映射转换,速写指令`emap:normal:常规商品,virtual:虚拟商品`
        goodsStatus: { $enum: [null, '销售中', '已下架', '缺货'] }, // 进行枚举转换,速写指令`enum:,销售中,已下架,缺货`
        goodsSkuList: (value) => value.map(item => item.attrs.join('-')), // 对数组的值直接处理
        isSale: Boolean, // 类型
        createTime: '#dateDefault', // 无参数预设格式化处理
        modifyTime: { $default: '无', $format: 'dateDefault:YYYY' }, // 速写指令`default:无 #dateDefault:YYYY`
    },
    provinces: (value) => value.split(','), // 转换成数组,可以通过扩展生成速写指令`#toArray`
}, originData)

// 输出数据
{
    list: [
        {
            code: 'SP10001',
            title: '标题:一件神奇的衣服',
            price: '¥1.20',
            goodsType: '常规商品',
            goodsStatus: '销售中',
            goodsSkuList: [
                '红色-XXL',
                '黑色-XXL',
            ],
            isSale: true,
            createTime: '2019/6/29',
            modifyTime: '无',
        },
        {
            code: 'SP10002',
            title: '标题:一条神奇的裤子',
            price: '¥2.20',
            goodsType: '虚拟商品',
            goodsStatus: '已下架',
            goodsSkuList: [
                '红色-XXL',
                '黑色-XXL',
            ],
            isSale: false,
            createTime: '2019/6/29',
            modifyTime: 2019,
        },
    ],
    provinces: ['中国', '美国', '日本'],
}

附录

Readme

Keywords

Package Sidebar

Install

npm i @shushu.pro/adapter

Weekly Downloads

0

Version

0.1.0

License

MIT

Unpacked Size

93.2 kB

Total Files

12

Last publish

Collaborators

  • sschen86