Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/mochi-c/pojoeditor

POJO可视化编辑方案,包含POJO到JsonSchema的解析器.Automatically generate JsonSchema according to the class information of the POJO
https://github.com/mochi-c/pojoeditor

jsonschema jsonschema-pojo pojo

Last synced: 3 months ago
JSON representation

POJO可视化编辑方案,包含POJO到JsonSchema的解析器.Automatically generate JsonSchema according to the class information of the POJO

Awesome Lists containing this project

README

        

[English](./README.md) | 简体中文

POJO EDITOR

POJO编辑器可以根据POJO的Class信息自动生成JosnSchema,搭配依据JsonSchema的可视化编辑工具轻松达到对POJO进行可视化,结构化,带有约束与校验的创建或编辑.

这可以使得非开发人员在编辑一些POJO对象描述的配置或者原始数据时更加直观高效,并能在一定程度上减少发生错误的情况.

## 使用示例

以下示例包含了编辑器支持的大部分类型

![image](https://github.com/mochi-c/POJOEditor/blob/master/docs/view.gif?raw=true)

该示例所对应的pojo如下

```java
public class ExampleClass {

String autoField;

//名称提示等
@JsonEditorUIMeta(title = "myTitle", desc = "myDesc", guide = "myGuide")
String titleDesGuide;

@JsonEditorUIMeta
String string;

@JsonEditorUIMeta(format = JsonEditorFormat.TEXT_AREA)
String textarea;

@JsonEditorUIMeta(format = JsonEditorFormat.TIME_SELECTOR)
@JsonEditorDateTimeSelector(resultFormat = "m-d H:i:S")
String timeWithSpecialResult;

@JsonEditorUIMeta(format = JsonEditorFormat.DATE_SELECTOR)
String date;

@JsonEditorUIMeta
int integer;

@JsonEditorUIMeta
double number;

@JsonEditorUIMeta
SimpleEnum simpleEnumSelection;

@JsonEditorUIMeta(format = JsonEditorFormat.SELECT)
@JsonEditorEnumBuilder(itemsBuilder = DynamicEnum.class)
String dynamicEnumSelection;

@JsonEditorUIMeta(format = JsonEditorFormat.TAGS)
List simpleEnumTags;

@JsonEditorUIMeta(format = JsonEditorFormat.TAGS)
@JsonEditorEnumBuilder(itemsBuilder = DynamicEnum.class)
List dynamicEnumTags;

@JsonEditorUIMeta
SimpleClass simpleClass;

@JsonEditorUIMeta(format = JsonEditorFormat.TABLE)
List table;

@JsonEditorUIMeta(format = JsonEditorFormat.TABS)
@JsonEditorArray(titleTemplate = "myName A:{{self.objA}} B:{{self.objB}}")
List specialNameTabs;

@JsonEditorUIMeta
List array;

@JsonEditorUIMeta(format = JsonEditorFormat.TABLE)
@JsonEditorArray(itemFormat = JsonEditorFormat.SELECT) //Can be omitted
@JsonEditorEnumBuilder(itemsBuilder = DynamicEnum.class)
List arrayStringToEnum;

@JsonEditorUIMeta(format = JsonEditorFormat.TABLE)
@JsonEditorArray(itemFormat = JsonEditorFormat.TIME_SELECTOR) //Can be omitted
@JsonEditorDateTimeSelector //Can be omitted
List arrayStringToTime;

public static class DynamicEnum implements IEnumItemBuilder {
@Override
public Map getItems() {
Map items = Maps.newHashMap();
items.put("Now", "Now");
items.put("TIME", System.currentTimeMillis() + "");
items.put("NAME", "SPECIALNAME");
return items;
}
}

public static enum SimpleEnum {
enumA,
enumB,
@JsonEditorUIMeta(title = "SpecialName")
enumC
}

public static class SimpleClass {
@JsonEditorUIMeta
String objA;
@JsonEditorUIMeta
String objB;
}

}
```

## 使用方式

编辑器由schemaParser和jsonEditor组合而成, 两者分别部署在服务之中,以下为一个典型的配置编辑流程参考

1. 后端服务从配置中心加载配置解析为pojo供上层使用

2. 后端解析pojo对应class的schema并由前端页面生成控件

3. 后端将该pojo实例json序列化并在编辑页面加载

4. 编辑页面完成修改由控件生成json数据回传到后端服务

5. 后端服务根据json数据反序列化得到新的配置信息并更新配置中心

### schemaParser

用于java端解析pojo格式生成jsonSchema,配合注解和过滤器可以实现field的过滤和交互方式的指定

### 引入

```xml

com.mochi-cell.tools
jsoneditorschemaparser
0.1.3

```

#### 使用

```java
JsonEditorParserBuilder.create(ExampleClass.class).parse();
JsonEditorParserBuilder.create(ExampleClass.class).setFieldFilters(Lists.newArrayList(SIMPLE_FIELD_FILTER.EVERY_FIELD)).addFormatDictionary(String.class, JsonEditorFormat.TEXT_AREA).parse();
```

### jsonEditor

提供可视化编辑的js控件,使用了开源的[json-editor](https://github.com/json-editor/json-editor),部分交互形式需要搭配selectize和flatpickr插件

#### 引入

npm

```javascript
npm install @json-editor/json-editor
```

cdn

```javascript

```

#### 使用

```javascript
const element = document.getElementById('editor_holder');
const editor = new JSONEditor(element, options);
```

#### 详细信息

## Base Annotation

### @JsonEditorUIMeta

JsonEditorUIMeta注解为field或class提供一些基本信息的配置,在ONLY_ANNOTATION的过滤器中也用作参与编辑的标志,对于没有标明该注解的成员,参与解析时使用默认值

| 成员 | 含义 | 默认值 |
| ---- | ---- | ---- |
| guide | 元素名称边上的 ? 提示,鼠标悬停上去会展开展示 | null 不显示提示
| desc | 描述信息,通常出现在编辑框下方 | null 不显示描述
| format | 用来指明需要使用的交互类型 | AUTO 根据类型自动转换
| title | 该元素的别名 | null 使用成员的命名 |

### @JsonEditorDependence

JsonEditorDependence注解可以会为json schema 追加 dependence option. 用以控制该 field 是否生效.
该注解是一个多重注解,多个条件需要同时生效,该field才会参与编辑,不参与编辑field不被显示,控件生成的json数据也不包含.

|成员|含义|
| ----- | ------------|
|dependenceKey|作为激活条件的field的name|
|dependenceValue|作为激活条件的field的值|

```java
class Test {
@JsonEditorUIMeta
@JsonEditorDependence(dependenceKey = "simpleEnumSelection", dependenceValue = "enumA")
@JsonEditorDependence(dependenceKey = "dynamicEnumSelection", dependenceValue = "Now")
String dependenceItem;

@JsonEditorUIMeta
SimpleEnum simpleEnumSelection;

@JsonEditorUIMeta(format = JsonEditorFormat.SELECT)
@JsonEditorEnumBuilder(itemsBuilder = DynamicEnum.class)
String dynamicEnumSelection;
}
```
上述例子中,只有当 simpleEnumSelection 为 enumA 且 dynamicEnumSelection 为 now 的时候 dependenceItem 才会生效,参与编辑.

## 交互方式(FORMAT)

对于各个字段的交互形式,可以通过JsonEditorUIMeta中的format来显示的指定.对于没有显示的指定的,解析器可以根据field的class自动转换,自动转换默认支持java的各基本类型包装类和容器,同时使用者也可以在配置中自己添加class到format的映射,默认的映射规则也是可以被覆盖的.

对于一些特殊的FORMAT存在对field的class限制,因为要从中获取一些必要的信息.还有一些format提供了一定的扩展功能,可以通过使用追加的注解来实现

前端页面编辑器中生成的json数据各个成员的类型与format是相对应的,对于一些特殊的类型,使用者需要自己处理前端页面编辑器得到的json数据到pojo的转换

### 支持的交互方式(FORMAT)

| 类型 | 效果 | Json类型 | 类型限制 | 扩展 |
| --- | --- | ------- | -------- | ---- |
|STRING|简单的文本框|String|×|×
|TEXT_AREA|可调整大小的文本框,适合较多的文字内容|STRING|×|×
|TIME_SELECTOR|时间选择器|STRING|×|√|
|DATE_SELECTOR|日期选择器|STRING|×|√|
|INTEGER|整数|NUMBER|×|×
|NUMBER|数字|NUMBER|×|×
|BOOLEAN|True,False下拉选择|BOOLEAN|×|×
|BOOLEAN_CHECK_BOX|勾选框|BOOLEAN|×|×
|ARRAY|完全展开的数组|ARRAY|√|√|
|TABLE|使用统一的表头展开的表格类型的数组|ARRAY|√|√|
|TABS|一次查看一个元素,重复使用视图的TAB页类型数组,页签在左侧|ARRAY|√|√|
|TABS_TOP|一次查看一个元素,重复使用视图的TAB页类型数组,页签在顶部|ARRAY|√|√|
|SELECT|下拉选择框,可以直接输入进行快捷搜索|STRING|√|√|
|TAGS|标签选择器|ARRAY[STRING]|√|√|
|OBJECT|递归解析Class对象,一般由解析器自动调用|OBJECT|-|-
|AUTO|根据默认类型转换自动选择|-|-|-|

### 默认的FORMAT转换

|JAVA类型|默认FORMAT类型|
| ----- | ------------|
|String|STRING|
|byte,short,int,long,及其包装类|INTEGER|
|float,double,及其包装类|NUMBER|
|boolean,Boolean|BOOLEAN|
|List/Set|ARRAY|
|enum|SELECTOR|
|List|TAGS|

### 指定Class到FORMAT的映射
````java
JsonEditorParserBuilder.create(ExampleClass.class).addFormatDictionary(String.class, JsonEditorFormat.TEXT_AREA);
````
### 类型限制的FORMAT

对于ARRAY,TABLE,TABS,TABS_TOP系列的ARRAY类型,要求对应的field一定是array,list,set,collection,因为解析器需要查询泛型的信息来递归解析array内部的信息

对于TAGS,要求对应的field一定是List\或者List\,对于List\还需要配合@ConfigEditorEnumBuilder注解提供枚举项

### FORMAT扩展

#### @JsonEditorArray
对ARRAY,TABLE,TABS,TABS_TOP系列的数组类型提供扩展

|成员|含义|
|----|---|
|titleItem|当List嵌套object时,使用对应object中的成员名作为List元素的别名,titleItem指明object中的成员名|
|showIndex|List元素的的名称中标明该元素在List中的下标,默认为true|
|titleTemplate|当List嵌套object时,List元素的别名的模板,其中i代表下标,self为list中的当前元素, 示例: {{i}} - {{self.xxx}} + {{self.bbb.aaa}}|
|itemFormat|强制指定List中元素的交互类型|

#### @JsonEditorDateTimeSelector
对TIME_SELECTOR,DATE_SELECTOR,时间/日期选择器提供扩展

|成员|含义|
|----|---|
|resultFormat|生成数据时的时间格式, 默认为 Y-m-d H:i:S|

#### @JsonEditorEnumBuilder
在SELECT,TAGS一类需要枚举的FORMAT中将String类型转换为枚举,使用该注解能够实现运行时动态的生成一枚举选项

|成员|含义|
|---|----|
|itemsBuilder|生成枚举项的接口,返回一个Map key为枚举的值,value为选择器中显示的别名|

### 一些特殊的FORMAT

对于Array系列的Format可以可以直接使用扩展注解可以改变泛型的类型例如使用JsonEditorDateTimeSelector将list元素内转换为时间选择器,使用JsonEditorEnumBuilder将元素转换为枚举.

对于SELECT,TAGS一类需要枚举的FORMAT中,对于Enum类型可以直接解析.选择框中支持别名,Enum通过在枚举值中使用ConfigEditorUIMeta中的title定义别名,String依靠注解中的构造器指明别名.编辑器中将显示别名,但得到的json数据将是原值

## FIELD过滤器

通过FIELD过滤器可以对class内的field进行过滤,用以确认哪些field是参与编辑的,编辑器自带了两个过滤器,其中SIMPLE_FIELD_FILTER是默认的

SIMPLE_FIELD_FILTER.SIMPLE_FIELD_FILTER 所有添加了@JsonEditorUIMeta注解的field参与编辑,其余的不参与
SIMPLE_FIELD_FILTER.EVERY_FIELD 所有成员都参与编辑

同时可以设置多个过滤器,使用者也可以自己按需要追加或者重置过滤器

存在多个过滤器时,所有的过滤器链式工作,全部通过的field才会参与编辑
````java
static class MyField implements IFieldFilter {
@Override
public boolean match(Field field) {
/**
* 该field是否生效,参与编辑
* true 生效
* false 不生效
*/
return true;
}
}

public static void main(String[] args) {
//重置过滤器
JsonEditorParserBuilder.create(ExampleClass.class).setFieldFilters(Lists.newArrayList(new MyField()));
//追加过滤器
JsonEditorParserBuilder.create(ExampleClass.class).addFieldFilter(new MyField());
}
````