通用解析

320 阅读4分钟
  • 简介

    自定义通用解析规则,适用于游戏中的各种数值配置,主要为策划提供新的配置方式,进而解决json配置的臃肿和不方便。

  • 解析规则

    该通用解析使用了java的反射机制,会根据配置中字符串的位置反射为对应对象的对象成员,再根据不同标识符解析为对应的类型,各种组合对象之间递归调用。

  • 标识符&对应作用

    • 对象成员分隔符,格式 1-2
    • , array和list分隔符,格式1,2,3....
    • {} 对象分隔符,在最外围的可以不加,组合对象需加,格式{1-2-3}
    • : ; map类型使用,格式 key:value1;key:value2;
    • 多态分隔符,格式 XXX@{1-2-3}
  • 支持类型&Main中对应实例函数

    • 单对象解析 initSingle
    • 对象数组解析 initArray
    • 成员为对象 initMemberObject
    • 多个成员为对象 initMemberObjects
    • 数组成员为数组List initMemberList
    • 成员为对象数组 initMemberArrObject
    • 成员为对象数组,并且list里边的对象再包含一个list initMemberArrObjectList
    • 数组成员为map initMemberMap
    • 数组成员为map map.value为Object initMemberMapObjectMap
    • 数组成员为map map.value为数组 initMemberMapArr
    • 数组成员为map map.value为对象数组 并且其中的对象还会再嵌套一层 initMemberMapArr3
    • 数组成员为map map.value为单对象 initMemberMapObject
    • 数组成员为map map.value为数组对象 initMemberMapObjects
    • 成员为array数组[] 基础类型 initArrayMember
    • 成员为array数组[] 数组对象 initArrayObjectMember
    • 多态 initDuotai
    • 多态 initDuotai2
  • 结构

    结构.png

    • helper.TypeEnum为 八个基础类型的枚举 + String枚举 + array枚举 + List枚举 + map枚举,枚举的作用都是根据传进来的参数str转为对应的类型然后返回,如
      int枚举结构.png
    • helper.VarietyTypeEnum为字符串对应的多态类的枚举,common-parse会根据@前的标志从VarietyTypeEnum中取出对应的class,然后根据配置用反射生成对象,如
      多态枚举.png
    • pojo文件夹下为对应要生成的类。
    • Main内有各个demo函数调用。
  • 该项目中涉及了反射的使用,在此列出相关代码

    • TypeEnum.OBJECT_TYPE中
      代码1.png

作用是根据对象中的成员Field取出具体的类型名字后利用Class.forName反射取出具体的Class,如Pojo.A; 再根据具体的Class调用getDeclaredConstructor获得构造器,再调用newInstance生成对应的Object对象,如最终生成Pojo.A对象。 此处要提及**getConstructor()getDeclaredConstructor()**区别,区别在于:

  • getDeclaredConstructor(Class<?>... parameterTypes) 这个方法会返回制定参数类型的所有构造器,包括public的和非public的,当然也包括private的,getDeclaredConstructors()的返回结果就没有参数类型的过滤了
  • getConstructor(Class<?>... parameterTypes) 这个方法返回的是上面那个方法返回结果的子集,只返回制定参数类型访问权限是public的构造器,getConstructors()的返回结果同样也没有参数类型的过滤。

在获得对应的Object之后会调用getDeclaredFields获得该Object中的各种Field,此处提及下getDeclaredFieldsgetFields的区别,区别在于:

  • getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
  • getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。

  • TypeEnum.ARRAY_TYPE中

代码2.png

此处的o如果是Field类型,**((Field) o).getType()可以获取Field的数组类型,而此处是要拿到数组的内的具体类型,如int[]要拿到int类型,所以再次调用getComponentType获取具体int类型; 而当o时对象数组类的时候,如People14[].class则直接((Class) o).getComponentType()**获取其中的具体类型,通过这种方式取出People.class。 之后便通过 **Object arr = Array.newInstance(cls, strList.size());反射实例化一个数组对象。如果要将数组对象的子对象塞入,则调用Array.set()**进行具体操作。


  • TypeEnum.LIST_TYPE和TypeEnum.MAP_TYPE中

代码3.png

该函数具体作用是获取Map中的泛型参数类型,具体实现如下

代码4.png
当o是Field类型的时候,使用getGenericType获取到Type,此时的Type类型是

代码5.png

之后便将Type强转为ParameterizedType后调用getActualTypeArguments获得Map中key和value的类型。

代码5.png

当为List的时候获取具体的泛型参数。

  • 运行示例
    • 单对象解析,配置如下:

配置1.png

反射成的目标类是:

目标类1.png

运行后会根据配置1中的字符串反射生成目标类的对象,如:

图片.png

更多示例可以查看项目 comon-parse,直接运行Main即可!!!