lowcode, 简单的json校验方案分享

前言:为什么要做

由于近几年低代码的火热,为了提高一些开发效率和降低开发成本,现在很多页面喜欢用json去描述。

但是呢,在这过程中也带来了一些问题。

由于某些异常情况,可能会导致我们的json数据发生错乱。比较常见的现象就是页面崩溃,需要由研发同学去排查问题。

由于json的数量通常较大且某些研发同学对代码的熟悉度有限,这给排错工作带来了巨大的挑战。可能需要人工检查几兆级别的json数据中的错乱数据。

在表现方面,页面崩溃并不是最严重的情况。例如,去年我负责一个与金钱挂钩的活动相关的低代码平台。如果由于json异常错乱导致错误的活动配置上线,那将带来更可怕的影响。

怎么做

首先回想一下,社区中本身是存在一个已经提供了相关校验功能的JSON Schema。但是有相当一部分人是不喜欢它的,因为它的特定格式和学习成本。我们有时候不希望自身设计的DSL还要受到限制。

但是既然它本身提供了校验的功能,我们能不能去写一个中间层去做一下JSON到JSON Schema的转换呢?JSON到JSON Schema的转换不太可能,因为拿不到类型定义,校验所需信息无从获取。但是我们还用TS呢,是不是可以先用TS先对JSON进行类型定义,然后可以做TS到JSON Schema的转换呢?

围绕着这个思路,社区中已有相关的实现方案。我这选其中一个给大家演示一下

栗子?:

比如我们设计了这么一段结构

interface Person {

  name: string

  age: number

  address?: {

    street: string

    city: string

    country: string

  }

}

期望在运行时可以生成一个方法,对下面的json数据进行格式校验。

{


    name: 11,

    age: 11

}

步骤1: 根据ts生成json-schema

ts生成json-schema,可以借助typescript-json-schema

常见类型存放目录type.ts

interface Person {

  name: string

  age: number

  address?: {

    street: string

    city: string

    country: string

  }

}

解析ts生成json-schema

import * as path from 'path'
import { buildGenerator, getProgramFromFiles } from 'typescript-json-schema'

function ts2jsonchema() {
  const program = getProgramFromFiles([
    path.resolve(__dirname, '../types/index.ts'),
  ])
  const generator = buildGenerator(program, { required: true })
  return generator!.getSchemaForSymbol('Person')
}

步骤2: 借助json-schema生成校验方法

校验库可以选择ajv

ajv的使用也非常简单,传入指定的jsonchema。就可以快速生成一个对应的校验方法

import Ajv from 'ajv'


function validate() {
  const ajv = new Ajv()
  const validate = ajv.compile(ts2jsonchema())
  return validate
}

步骤3: 验证

仅需简单几个步骤,我们已经快速构建一了一个对Person类json的校验方法,简单写一个单元测试验证一下吧。

{


    name: 11,

    age: 11

}

这段数据肯定是不满足的,因为我们定义的name是string。并且我们希望能给出一个错误的定位,像json-schema标准格式这样

{


  instancePath: '/name',
  schemaPath: '#/properties/name/type',
  keyword: 'type',
  params: { type: 'string' },
  message: 'must be string'
}

jest代码如下:

import validate from '../validate'


describe('validate', () => {
  it('base', () => {
    const validateFn = validate()
    const valid = validateFn({
      name: 11,
      age: 11
    })
    // name must be string
    expect(valid).toBe(false)
    expect(validateFn.errors).toEqual([
      {
        instancePath: '/name',
        schemaPath: '#/properties/name/type',
        keyword: 'type',
        params: { type: 'string' },
        message: 'must be string'
      }
    ])
  })
})

需要注意:

生成json-schema、与json-schema的校验。这两块的性能都不是很好。生成json-schema这块我们可以不必关注,我们一般可以在编译阶段去做。但是校验这块,尽量只做前置校验或后置兜底的操作。如果不care性能问题,那就无所畏惧了?

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYWDmjZp' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片