JSON Schema动态表单配置规则应用

目录

前言

一、JSON Schema 规范

二、schema字段描述

三、JSON Schema 应用

一、业务描述

二、模版数据表设计

  三、规则表设计

四、构造Groovy 脚本参数Map

五、执行Groovy 脚本


前言

Formily 提供了 JSON Schema、JSX Schema、纯 JSX 三种开发模式。由于 JSON 可以序列化保存到数据库中,所以 JSON Schema 的方式非常适合后端动态渲染表单,前端完全不需要维护 schema,只需利用 Formliy 提供的 SchemaForm 来渲染后端返回的 schema 即可。我们仅需通过 Form Builder 或者 Page Designer 之类的工具来输出 JSON Schema,然后交给 SchemaForm 或者 PageEngine 之类的组件来渲染。


一、JSON Schema 规范

JSON Schema 是一个社区推动的 JSON 文件协议,用于规范 JSON 文件内容。它与平台无关,可以描述任意复杂的数据结构,相比 XML,JSON 的描述格式更加紧凑,可读性更好。JSON Schema 在 JSON 的格式上,加入了一些列的标准化属性,用于描述结构化数据。Formily 遵循 JSON Schema 使用最广泛的[draft-07 标准](Specification Links

我们可以借助 ajv 这类 JSON Schema 验证工具,来认识不同 Schema 规范的区别,详情可参考 [draft-07 (and draft-06)](Ajv JSON schema validator)。

用 JSON Schema 来描述表单适合于低代码或者数据中台的快速开发。前端不需要维护 schema,schema 可以存在后端,随意分发动态渲染。

二、schema字段描述

 演示地址:https://xrender.fun/schema-builder

{
  "bsonType": "object",// 固定节点
  "description": "表的描述","required": [],// 必填字段,比如name,age
  "permission": {
    "read": false,// 前端非admin的读取记录权限控制。默认值是false,即可以不写。可以简单的true/false,也可以写表达式
    "create": false,// 前端非admin的新增记录权限控制。默认值是false,即可以不写。可以简单的true/false,也可以写表达式
    "update": false,// 前端非admin的更新记录权限控制。默认值是false,即可以不写。可以简单的true/false,也可以写表达式
    "delete": false,// 前端非admin的删除记录权限控制。默认值是false,即可以不写。可以简单的true/false,也可以写表达式
    "count": false // 前端非admin的求数权限控制。默认值是true,即可以不写。可以简单的true/false,也可以写表达式
    // 对数据进行数量统计时(包括count方法、及groupField内的count操作)均会同时触发表级的count权限及read权限
  },"properties": { // 表的字段清单
    "_id": {
      "description": "ID,系统自动生成"
    },"other": { // 字段名称,每个表都会带有_id字段
      "bsonType": "",// 字段类型,可选值: string | password | int | double | bool | date | timestamp | object | file | array
      "arrayType": "file",// 指定字段类型为数时,其元素项类型,bsonType="array" 时有效。
      "title": "",//<string> 标题,开发者维护时自用。在schema2code生成前端表单代码时,默认用于表单项前面的label
      "description": "",//<string> 描述,开发者维护时自用。在生成前端表单代码时,如果字段未设置componentForEdit,且字段被渲染为input,那么input的placehold将默认为本描述
      "defaultValue": "",//<string | object>默认值
      "forceDefaultValue": "",//<string | object> 强制默认值,不可通过clientDB的代码修改,常用于存放用户id、时间、客户端ip等固定值。
      "required": [],//<array> 是否必填。支持填写必填的下级字段名称。required可以在表级的描述出现,约定该表有哪些字段必填。也可以在某个字段中出现,如果该字段是一个json对象,可以对这个json中的哪些字段必填进行描述。
      "enum": [],//<array> 字段值枚举范围,数组中至少要有一个元素,且数组内的每一个元素都是唯一的。enum最多只可以枚举500条
      "enumType": "",//<string> 字段值枚举类型,可选值tree。设为tree时,代表enum里的数据为树形结构。此时schema2code可生成多级级联选择组件
      "fileMediaType": "",//<string> 文件类型,bsonType="file" 时有效,可选值 all|image|video 默认值为all,表示所有文件,image表示图片类型文件,video表示视频类型文件
      "fileExtName": "",//<string>文件扩展名过滤,bsonType="file" 时有效,多个文件扩展名用 "," 分割,例如: jpg,png,
      "maximum": 20,//<number>如果bsonType为数字时,可接受的最大值
      "exclusiveMaximum":,//<boolean>bsonType为数字时,是否排除 maximum
      "minimum":,//<number>如果bsonType为数字时,可接受的最小值
      "exclusiveMinimum",是否排除 minimum
      "minLength",//<number>bsonType = String | Array时,限制字符串或数组的最小长度
      "maxLength",//<number>bsonType = String | Array时,限制字符串或数组的最大长度
      "trim": "both",//<boolean> bsonType = String 时,去除空白字符。可选值none|both|start|end,默认值none trim优先级高于其它驗证,它会在先去掉空格之后,再进行驗证。
      "format": //枚举类型,可选值 url | email。设置字段数据格式。目前只支持这二种格式。数据不符合此格式时无法录入。
      "pattern": //<string>正则表达式,比如设置手机号码正则,如果该字段值不符合手机号正则,则录入失败。  验证手机号正则:"pattern": "^\\+?[0-9-]{3,20}$"

        "validateFunction": "",//<string | object>扩展校验函数名,用于校验该字段值是否符合要求
      /* 值类型为:String 时表示校验函数名
      值类型为object格式:
       {
         "name": """  //<string>校验函数名
         "client": true //<boolean>默认值true。值为true时客户端也可以在生成的代码中改为自己的校验函数,此时客户端的校验仍然生效(不懂)
       } */

      "permission": { //<object> 字段的数据库权限,仅write、read
        "write": true,"read": true
      },"errorMessage": "",//<string|Objeect>当数据写入或更新时,校验数据合法性失败后,返回的错误提示
      // 比如:
      // "errorMessage": "{title}不能为空"  {title} 为当前字段设置的title属性值
      // 或者指定具体出错点
      // "errorMessage": {
      //     "required": "{title}不能为空",//当required不满足时,出错提示内容
      //     "minLength": """,//当minLength不满足时,出错提示内容
      //     "maximum": """,//当maximum不满足时,出错提示内容
      //     "pattern":,//当pattern不满足时,出错提示内容
      //     "format": "{title}格式无效"  //当format不满足时,出错提示内容
      //   }
      "foreignKey": "",//<string>外键索引。关联字段。表示该字段的原始定义指向另一个表的某个字段,值的格式为:关联表名.字段名。关联字段定义后可用于联表查询,通过关联字段合成虚拟联表,极大的简化了联表查询的复杂度
      "parentKey": "",//<string>同一个数据表内父级的字段。 用于树状(tree)数据查询
      "label": "",//<string> schema2code的配置。字段标题。schema2code生成前端代码时,渲染表单项前面的label标题。如果不填,会使用title属性。适用于title不便显示在表单项前面的情况
      "group": "",//<string> schema2code的配置。分组id。schema2code生成前端代码时,多个字段对应的表单项可以合并显示在一个uni-group组件中
      "order": 0,//<int> schema2code的配置。表单项排序序号。

      //!!!!! componentForEdit 类型为对象和数组。测试数组不成功。对象可以。~!!!!
      "componentForEdit": {},//<object | array> 生成前端编辑页面文件时(add.vue、edit.vue),使用什么组件渲染这个表单项。比如使用input输入框。格式:
      /* 示例一:简单的组件
      {
        "name": "input",//此字段所用组件名
        "props": { //设置组件属性
            "placeholder": "请输入昵称"  //逻辑或数值类型要加:号,比如:  ":disabled": false
        }
        //"children": '' //<string> 子组件名。
        //"childrenData": [] //<array> 子组件数据
      }
      示例二:带子组件的组件
      {
          "name": "select","children": "<option value=\"{value}\">{label}</option>","childrenData": [{"label": "中文简体","value": "zh-cn"}]
      } */

      "componentForShow": [] // <object | array>生成前端展示页面时(list.vue、detail.vue),使用什么组件渲染。比如使用uni-dateformat格式化日期。
    }
  },"fieldRules": [
    /* 字段之间的约束关系。比如字段开始时间小于字段结束时间。也可以只校验一个字段。支持表达式
    注意:这里的rule是为符合条件,而不是不满足条件
    {
      "rule": "end_date == null || end_date != null && create_date < end_date",// 校验规则
      "errorMessage": "创建时间和结束时间不匹配",// 错误提示信息(仅在新增时生效,更新数据时不会提示此信息)
      "client": false // schema2code时,当前规则是否带到前端也进行校验。目前此属性暂不生效,fieldRules不会在客户端校验数据,仅会在云端进行校验
    } */
  ]
}

三、JSON Schema 应用

、业务描述

在项目开发中,我们经常需要定义一些规则,根据规则匹配处理相应的业务。比如在广告投放业务中,我们有以下规则的动态组合回传用户关键行为【注册,激活,支付等转化】。

  • 用户阅读时长 + 用户收益

      

  • 广告曝光数     + 用户收益

       

  • 用户支付金额

、模版数据表设计

如上,根据不同条件组合回传用户的关键行为非常适合用动态表单开发。首先我们先定义模版表

字段名称 字段类型 字段描述
id BIGINT(20) 主键
groovy_code VARCHAR(64) Groovy模版编码
groovy_name VARCHAR(64) Groovy模版名称
content TEXT Groovy脚本
schema_json TEXT 数据结构
status TINYINT(4) 状态  1:启用  2:停用

   content:Groovy脚本返回Boolean 值,用于规则是否匹配成功。

  用户阅读时间投放模版Groovy 脚本

import java.util.Date;
import java.util.Map;

import cn.hutool.core.convert.Convert;
import com.xinwu.shushan.core.common.ApplicationContextHelper;
import com.xinwu.shushan.launch.infra.cache.UserReadTimeCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Groovy {
    private static Logger logger = LoggerFactory.getLogger("launch_book_readTime");

    public Boolean match(Map<String,Object> map) {
        Integer expectedReadTime = Convert.toInt(map.get("readTime"));
        Integer userId = (Integer) map.get("userId");
        Date date = (Date) map.get("date");
        UserReadTimeCache userReadTimeCache = ApplicationContextHelper.getBean(UserReadTimeCache.class);
        int actualReadBookTime = userReadTimeCache.getReadTime(date,userId);

        logger.info("template-launch_book_readTime#userId={},expectedReadTime={},actualReadBookTime={}",userId,expectedReadTime,actualReadBookTime);

        return actualReadBookTime >= expectedReadTime;
    }
}

用户阅读时间 schema_json 数据结构:

{
    "type":"object","properties":{
        "readTime":{
            "title":"阅读时长(秒)","type":"number","defaultValue":300,"props":{
                "placeholder":"请输入阅读时长"
            },"required":true,"min":0,"widget":"inputNumber"
        }
    },"displayType":"row","maxWidth":"340px"
}

  三、规则表设计

launch_config 投放配置表定义

字段名称 字段类型 字段描述
id INT(10) 主键
channel_type VARCHAR(32) 渠道
product_type INT(11) 产品类型
advertiser_id VARCHAR(64) 广告主ID
conversion VARCHAR(128) 转化
groovy_code VARCHAR(64) 模版code
condition_json VARCHAR(1024) 条件[json schema 表单值]

、构造Groovy 脚本参数Map

private Map<String,Object> buildMap(Integer userId,Integer productType,Date date,String conditionJson) {
        Map<String,Object> map = Maps.newHashMap();
        
        map.put("date",date);
        map.put("userId",userId);
        map.put("productType",productType);


        if (StringUtils.isNotBlank(conditionJson)) {
            Map<String,Object> conditionMap = JSON.parseObject(conditionJson,Map.class);
            map.putAll(conditionMap);
        }

        return map;
    }

、执行Groovy 脚本

   public Boolean proceed(String templateCode,Map<String,Object> map) {
        GroovyObject groovyObject = groovyRepository.getByCode(templateCode);

        Invocation invocation = new Invocation(groovyObject,"match",new Object[]{map});
        Object result = invocation.proceed();

        return (Boolean) result;
    }

原文地址:https://blog.csdn.net/yangyanping20108/article/details/132483324

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读2.4k次。最近要优化cesium里的热力图效果,浏览了网络上的各种方法,发现大多是贴在影像上的。这么做好是好,但是会被自生添加的模型或者其他数据给遮盖。其次是网上的方法大多数是截取成一个矩形。不能自定义的截取自己所需要的。经过尝试,决定修改下cesium heatmap,让他达到我们需要的要求。首先先下载 cesium heatmap包。其中我们可以看到也是通过叠加entity达到添加canvas的方法绘制到地图上。我们先把这一段代码注释} else {} };
文章浏览阅读1.2w次,点赞3次,收藏19次。在 Python中读取 json文件也可以使用 sort ()函数,在这里我介绍一个简单的示例程序: (4)如果我们想将字符串转换为列表形式,只需要添加一个变量来存储需要转换的字符串即可。在上面的代码中,我们创建了一个名为` read`的对象,然后在文件的开头使用`./`关键字来命名该对象,并在文件中定义了一个名为` json`的变量,并在其中定义了一个名为` json`的字段。比如,我们可以使用 read方法读取 json文件中的内容,然后使用 send方法将其发送到 json文件中。_python怎么读取json文件
文章浏览阅读1.4k次。首字母缩略词 API 代表应用程序编程接口,它是一种设备,例如用于使用编程代码发送和检索数据的服务器。最常见的是,该技术用于从源检索数据并将其显示给软件应用程序及其用户。当您访问网页时,API 的工作方式与浏览器相同,信息请求会发送到服务器,如何在 Windows PC 中手动创建系统还原点服务器会做出响应。唯一的区别是服务器响应的数据类型,对于 API,数据是 JSON 类型。JSON 代表 JavaScript Object Notation,它是大多数软件语言中 API 的标准数据表示法。_api是什么 python
文章浏览阅读802次,点赞10次,收藏10次。解决一个JSON反序列化问题-空字符串变为空集合_cannot coerce empty string ("") to element of `java.util.arraylist
文章浏览阅读882次。Unity Json和Xml的序列化和反序列化_unity json反序列化存储换行
文章浏览阅读796次。reader.readAsText(data.file)中data.file的数据格式为。使用FileReader对象读取文件内容,最后将文件内容进行处理使用。_a-upload 同时支持文件和文件夹
文章浏览阅读775次,点赞19次,收藏10次。fastjson是由国内的阿里推出的一种json处理器,由java语言编写,无依赖,不需要引用额外的jar包,能直接运行在jdk环境中,它的解析速度是非常之快的,目前超过了所有json库。提示:以下是引用fastjson的方法,数据未涉及到私密信息。_解析器用fastjson还是jackson
文章浏览阅读940次。【Qt之JSON文件】QJsonDocument、QJsonObject、QJsonArray等类介绍及使用_使用什么方法检查qjsondocument是否为空
文章浏览阅读957次,点赞34次,收藏22次。主要内容原生 ajax重点重点JSON熟悉章节目标掌握原生 ajax掌握jQuery ajax掌握JSON第一节 ajax1. 什么是ajaxAJAX 全称为,表示异步的Java脚本和Xml文件,是一种异步刷新技术。2. 为什么要使用ajaxServlet进行网页的变更往往是通过请求转发或者是重定向来完成,这样的操作更新的是整个网页,如果我们只需要更新网页的局部内容,就需要使用到AJAX来处理了。因为只是更新局部内容,因此,Servlet。
文章浏览阅读1.4k次,点赞45次,收藏13次。主要介绍了JsonFormat与@DateTimeFormat注解实例解析,文中通过示例代码介绍的非常详细,对大家的学习 或者工作具有一定的参考学习价值,需要的朋友可以参考下 这篇文章主要介绍了从数据库获取时间传到前端进行展示的时候,我们有时候可能无法得到一个满意的时间格式的时间日期,在数据库中显 示的是正确的时间格式,获取出来却变成了时间戳,@JsonFormat注解很好的解决了这个问题,我们通过使用 @JsonFormat可以很好的解决:后台到前台时间格式保持一致的问题,
文章浏览阅读1k次。JsonDeserialize:json反序列化注解,作用于setter()方法,将json数据反序列化为java对象。可以理解为用在处理接收的数据上。_jsondeserialize
文章浏览阅读2.7k次。labelme标注的json文件是在数据标注时产生,不能直接应用于模型训练。各大目标检测训练平台或项目框架均有自己的数据格式要求,通常为voc、coco或yolo格式。由于yolov8项目比较火热,故此本博文详细介绍将json格式标注转化为yolo格式的过程及其代码。_labelme json 转 yolo
文章浏览阅读790次,点赞26次,收藏6次。GROUP_CONCAT_UNORDERED(): 与GROUP_CONCAT类似,但不保证结果的顺序。COUNT_DISTINCT_AND_ORDERED(): 计算指定列的不同值的数量,并保持结果的顺序。COUNT_ALL_DISTINCT(): 计算指定列的所有不同值的数量(包括NULL)。AVG_RANGE(): 计算指定列的最大值和最小值之间的差异的平均值。JSON_OBJECT(): 将结果集中的行转换为JSON对象。COUNT_DISTINCT(): 计算指定列的不同值的数量。_mysql json 聚合
文章浏览阅读1.2k次。ajax同步与异步,json-serve的安装与使用,node.js的下载_json-serve 与node版本
文章浏览阅读1.7k次。`.net core`提供了Json处理模块,在命名空间`System.Text.Json`中,下面通过顶级语句,对C#的Json功能进行讲解。_c# json
文章浏览阅读2.8k次。主要介绍了python对于json文件的读写操作内容_python读取json文件
文章浏览阅读770次。然而,有时候在处理包含中文字符的Json数据时会出现乱码的情况。本文将介绍一种解决Json中文乱码问题的常见方法,并提供相应的源代码和描述。而某些情况下,中文字符可能会被错误地编码或解码,导致乱码的出现。通过适当地控制编码和解码过程,我们可以有效地处理包含中文字符的Json数据,避免乱码的发生。通过控制编码和解码过程,我们可以确保Json数据中的中文字符能够正确地传输和解析。为了解决这个问题,我们可以使用C#的System.Text.Encoding类提供的方法进行编码和解码的控制。_c# json 中文编码
文章浏览阅读997次。【代码】【工具】XML和JSON互相转换。_xml 转json
文章浏览阅读1.1k次。json path 提取数据_jsonpath数组取值
文章浏览阅读3w次,点赞35次,收藏36次。本文主要介绍了pandas read_json时ValueError: Expected object or value的解决方案,希望能对学习python的同学们有所帮助。文章目录1. 问题描述2. 解决方案_valueerror: expected object or value