Skip to content

中文文档

jxz_211 edited this page Jul 25, 2021 · 4 revisions

本文档已经不更新,新的文档放在 https://suchjs.github.io/vp-suchjs 这个Github Pages上了,里面介绍得更全面并保持更新。

使用方式

使用英文冒号(:)作为描述开始标记符,第一个冒号后面标注为类型,目前已支持的内置类型有string,number,date,regexp,ref,id,后续可能添加更多通用类型,但更希望使用者自行扩展类型,后面将会讲到如何来扩展类型

// 示例
Such.as(":string{10,20}") //结果类似a,0a(3akl .ka

方法API

  • Such.as(mockData:any, config?:{ instance:true })

mockData参数可以是类似上面的描述表达式,也可以是一个具体的数据结构、或者具体的数据值,将会依据结构逐级mock数据,当config的instance设置为true后,将返回一个Such的实例,实例需要通过调用instance.a()方法才能生成mock数据

// 示例
Such.as({
  a:1,
  b:":number[2,5]:%d"
});
  • instance.a()

如上所述,可以多次调用instance实例的.a方法来生成mock数据

// 示例
const instance = Such.as(':string{10,20}',{
  instance: true
});
instance.a();
instance.a();
  • Such.define(type:string,fromType:string|generate:function|{generate,param,init,...},rule:string|{generate, param, init})

定义一个自定义类型,这里有三种定义方式,第一个参数总为类型名。

// 第二个参数是个generate函数,每次模拟都会执行一次
Such.define('boolean',() => {
  return Such.utils.isOptional();
});
Such.define('abc',{
  param: '',//默认固定配置
  init(){
  },
  generate(){
    const { params } = this;
    // 这里通过获取到的params各个参数,自行决定如何生成最终结果
  }
});
// 第三种模式应该是应用最广泛的方式,表示从一个已有模式里固定某些参数等、或者覆盖generate方法等
Such.define('lowercase','string','[97,122]');
Such.define('other','string',{
  param: '',
  init(){},
  generate(){}
});
  • Such.assign(key, value:function|..., stillVar:boolean)

定义一些全局变量或者全局方法,这些方法将可在最后的modifier函数中用到。

Such.assign('wrapper',(result, prefix, suffix) => {
  return (prefix || '') + result + (suffix || '');
});
Such.assign('ellipsis','...');
// 然后就可以项像下面这么调用了
Such.as(':string{10,20}:@wrapper("test:",ellipsis)')

值参数配置

  1. [ min, max ]

对于数字类型,它表示大于等于min,小于等于max的一个数. 对于字符串类型,它表示字符码点范围

  1. {min, max?}|{number}

返回个数介于min和max之间,或者指定number次,通常用来表示字符出现次数

  1. %format

格式化参数,通常用来对数字类型、时间类型等的格式化说明

  1. /abc/ius

正则表达式参数,将会按照正则表达式进行反向解析,不过这里限制了一些功能、也扩展了一些功能,后面将会详细解释

  1. #[a=1,flag,c="233"]

配置参数,通常用来定义一些辅助变量,可以让数据模拟变得更精细化

  1. @ucfirst|wrapper("ta说:","...")

modifier方法,将在已生成数据的基础上通过定义的全局方法和变量对数据进行更一步的处理,此外如果发现modifier方法不存在,会尝试对结果进行原生方法调用。自定义全局方法时,第一个参数会自动注入为前面generate出来的结果。

  1. &./abc,../bc/ef

获取一个当前数据结构的引用,单个引用会以当前引用数据直接返回,多个引用将得到一个引用数组,可以在方法参数里做一些进一步的输出

key参数配置

  1. ?

表示该字段可选

Such.as({
  "a?":1
});
// 可能的结果
{
  a:1
}
{
  // 空
}
// 也可以和范围符配合使用,表示要么有指定个数,要么没有
Such.as({
  "a?{3}":[1,2]
});
// 可能的结果
{
  // 空
}
{
  a: [1,2,1]
}
  1. {min, max}|{number}

和值参数配置,key的长度范围通常用来描述数组的长度个数

Such.as({
  'job{0,3}':['fe','rd','pd']
});
// 可能的结果
/*一条也没有,字段就不存在了*/
{
  // nothing
}
/*只有一条,非数组*/
{
  'job': 'fe'
}
/*两条*/
{
  'job': ['fe','pd']
}
  1. [ min, max ]

和上面的长度范围一样,不过当允许数组长度为1个或0个时,其表示最终数据总是数组

Such.as({
  'job[0,3]': ['fe','rd','pd']
});
// 可能的结果
/*一条也没有,空数组*/
{
  job: []
}
/*只有一条*/
{
  job: ['fe']
}
/*多条*/
{
  job: ['fe', 'pd']
}
  1. :

辅助选择符,主要和上面范围参数配合使用,表示重复的数据是从数组中随机选择一个进行重复,而不是所有都随机

Such.as({
  'job:[0,3]': ['fe','rd','pd']
});
/*多条*/
{
  job: ['fe','fe','fe']
}

关于数字格式化的说明

对于number类型,可以使用类似于c里printf方法进行格式化,需要注意的是对于浮点数转化为整数时,会采取四舍五入的方法,这表示如果设置的范围是[1,2.6],这种的数据最终转化成%d时可能会得到3,大于实际想要设置的范围

关于字符串码点范围设置

对于string类型,码点范围可以表示为多个区间的模式[65-99,97-122],这样可以提供多种字符选择。也可以表示为[\u4e00,\u9fa5]这种unicode模式。

关于正则表达式的说明

  • 不支持^$匹配开始和结束标记符,设置了也将被忽略并给出警告。这是因为在反向解析的时候设置开始结束标记的意义并不是太大,将有可能造成没法匹配的情况,同时给解析带来困难。
  • 不支持前瞻后顾(?!xxx)(?=xxx)模式,原理同上,但如果出现前瞻后顾,程序会报错而不是选择忽略。
  • 支持了(?[a-z]+(?:\.com|\.cn))命名匹配,配合#[domain="so.com|360.cn"]设置的变量一块使用会非常有用,这样在默认状态下将会按已有模式进行模拟,在有config变量的情况会以变量按照|分隔分组后,随机取一个进行替换,但分组后的数据必须与已有模式相兼容,否则会报错
  • 将支持命名表达式名按冒号:分隔的表达模式,可以对应命名内的分组,这样可以通过config配置来选择分组。举例来说(?<v4:v6>xxxx|xxxxxx),假如这是一个ip的正则表达,可以是ip v4也可以是ip v6,但现在想要只模拟ip v4,可以在设置变量#[v4]为true的方式,使其只模拟v4对应的第一个分组,亦可设置#[v4=false]或#[v6]来匹配到v6对应的第二个分组

关于moidfier方法调用

以使用wrapper方法为例,可以看一下简单实现

Such.assign('isay', '我说:');
Such.assign('wrapper',(result, prefix, suffix) => {
  // result是拿到的解析后的值
  return prefix + result + suffix;
});
Such.as(':string{5,10}:@wrapper(isay,"...")');
// 得到结果
"我说:akljsgs..."
// 同时也可以用config变量进行覆盖
Such.as(':string{5,10}:@wrapper(isay,"..."):#[isay="他说:"]');
// 得到结果
"他说:ksksgd..."