Gson 自动生成适配器插件

2023-12-05

在json解析方面 我们常见有下面几方面困扰

1. moshi code-gen能自动生成适配器,序列化效率比gson快,但是自定义程度不如gson,能java kotlin共存 且解决了默认值的问题
2.gson api 强大自由,但是 第一次gson的反射缓存比较慢,而且生成对象都是反射,除非主动注册com.google.gson.InstanceCreator 这个人工机械
3.kotlin ks 效率还行,但是不支持java  api自由性没有gson强
目前可能更偏向gson 同时也要解决默认值的问题

最大的一处难点是在jvm 获取申明的枚举,先看一下gson是怎么解决的

  private static final class EnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
    private final Map<String, T> nameToConstant = new HashMap<String, T>();
    private final Map<T, String> constantToName = new HashMap<T, String>();

    public EnumTypeAdapter(final Class<T> classOfT) {
      try {
        // Uses reflection to find enum constants to work around name mismatches for obfuscated classes
        // Reflection access might throw SecurityException, therefore run this in privileged context;
        // should be acceptable because this only retrieves enum constants, but does not expose anything else
        Field[] constantFields = AccessController.doPrivileged(new PrivilegedAction<Field[]>() {
          @Override public Field[] run() {
            Field[] fields = classOfT.getDeclaredFields();
            ArrayList<Field> constantFieldsList = new ArrayList<Field>(fields.length);
            for (Field f : fields) {
              if (f.isEnumConstant()) {
                constantFieldsList.add(f);
              }
            }

            Field[] constantFields = constantFieldsList.toArray(new Field[0]);
            AccessibleObject.setAccessible(constantFields, true);
            return constantFields;
          }
        });
        for (Field constantField : constantFields) {
          @SuppressWarnings("unchecked")
          T constant = (T)(constantField.get(null));
          String name = constant.name();
          SerializedName annotation = constantField.getAnnotation(SerializedName.class);
          if (annotation != null) {
            name = annotation.value();
            for (String alternate : annotation.alternate()) {
              nameToConstant.put(alternate, constant);
            }
          }
          nameToConstant.put(name, constant);
          constantToName.put(constant, name);
        }
      } catch (IllegalAccessException e) {
        throw new AssertionError(e);
      }
    }
    @Override public T read(JsonReader in) throws IOException {
      if (in.peek() == JsonToken.NULL) {
        in.nextNull();
        return null;
      }
      return nameToConstant.get(in.nextString());
    }

    @Override public void write(JsonWriter out, T value) throws IOException {
      out.value(value == null ? null : constantToName.get(value));
    }
  }

gson的实现 是第一次反射(TypeAdapter 对于rawType gson本身会缓存)
他这个时候能读取到class,但是编译注解这个时候并不能得到class,
那么又查询了官方文档,官方的解释不在是class 而是Element和TypeName的类

翻译如下:
宽松地说,返回直接被该元素包围的元素。 类或接口被认为包含它直接声明的字段、方法、构造函数和成员类型。 包包含其中的顶级类和接口,但不被视为包含子包。 模块将包包含在其中。 封闭的元素可以包括隐式声明的强制元素。 其他种类的元素目前不被认为包含任何元素; 但是,随着 API 或编程语言的发展,这种情况可能会发生变化。
返回:
包含的元素,如果没有则为空列表
API注意事项:
可以使用 ElementFilter 中的方法来隔离某些类型的元素。
也可以看看:
TypeElement.getEnclosureElements、PackageElement.getEnheldElements、ModuleElement.getEnheldElements、Elements.getAllMembers
吉林斯
8.8.9 默认构造函数
吉林斯
8.9 枚举
修改
9
规格
联合项目管理系统

那么我理解jvm 元数据matadata存储在这个数组里面

我打印了一下 得到枚举的全部申明 包括enum_entry(不是enum class)还有valueOf等方法

枚举数据在元数据里面 values(),valueOf(java.lang.String),HELLO,HI,FINE,THANKS,intValue,TestEnum(int),getIntValue()

得按类型过滤出 申明的enum_constant

        val enumConstants = enumElement?.enclosedElements?.filter {
            it.kind == ElementKind.ENUM_CONSTANT
        } ?: listOf()

最终折腾了半天 终于出来了


import com.google.gson.annotations.SerializedName
import javax.lang.model.element.ElementKind

/**
 * xxf:生成编译时枚举常量池生成hashmap
 */
internal class EnumTypeParser {
    internal val nameToConstant: MutableMap<String, Any> = mutableMapOf()
    internal val constantToName: MutableMap<Any, String> = mutableMapOf()

    /**
     * 枚举数据在元数据里面 values(),valueOf(java.lang.String),HELLO,HI,FINE,THANKS,intValue,TestEnum(int),getIntValue()
     * @param enumElement
     */
    constructor(enumElement: javax.lang.model.element.Element?) {
        val enumConstants = enumElement?.enclosedElements?.filter {
            it.kind == ElementKind.ENUM_CONSTANT
        } ?: listOf()
        enumConstants.forEach { constant ->
            val annotation: SerializedName? = constant.getAnnotation(SerializedName::class.java)

            var name = constant.simpleName.toString()
            //本身名字
            nameToConstant[name] = constant


            //注解名字 和别名名字
            if (annotation != null) {
                name = annotation.value
                for (alternate in annotation.alternate) {
                    nameToConstant[alternate] = constant
                }
            }

            nameToConstant[name] = constant
            constantToName[constant] = name
        }
        //排序一下 代码好看一点
        nameToConstant.toSortedMap().run {
            nameToConstant.clear()
            nameToConstant.putAll(this)
        }

        //排序一下 代码好看一点
        constantToName.toSortedMap(Comparator { o1, o2 ->
            constantToName[o1]!!.compareTo(constantToName[o2]!!)
        }).run {
            constantToName.clear()
            constantToName.putAll(this)
        }
    }

}

运行效果:

这样就替代了gson 枚举0反射,同样的读写都是o(1)

更多类型的实现 请参考我的开源项目 gson_plugin
这个可能是业界最快的json解析方式 最快的json解析框架

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Gson 自动生成适配器插件 的相关文章

随机推荐

  • 拒绝写重复代码,试试这套开源Spring Boot组件,效率翻倍!

    1 简介 Graceful Response是一个Spring Boot技术栈下的优雅响应处理器 提供一站式统一返回值封装 全局异常处理 自定义异常错误码 等功能 使用Graceful Response进行web接口开发不仅可以节省大量的时
  • android 13.0 去掉usb授权提示框 默认给予权限

    1 概述 在13 0的系统rom产品开发中 在进行iot关于插入usb设备的开发过程中 在插入usb设备时会弹出usb授权提示框 也带来一些不便 这个需要默认授予USB权限 插拔usb都不弹出usb弹窗所以这要从usb授权相关管理页默认给与
  • uniapp打包的h5项目多了接口调用https://api.next.bspapp.com/client

    产生跨域问题 这个实际上是因为该项目在manifest json文件中勾选了 uni统计配置 导致的 取消勾选就可以了 如果是小程序项目 在小程序开发者工具中添加可信任域名就可以了 可以看看下面这个链接内容 uni app H5跨域问题解决
  • 【go语言开发】编写单元测试

    本文主要介绍使用go语言编写单元测试用例 首先介绍如何编写单元测试 然后介绍基本命令的使用 最后给出demo示例 文章目录 前言 命令 示例 前言 在go语言中编写单元测试时 使用说明 测试文件命名 在 Go 语言中 测试文件的命名应与被测
  • RestTemplate

    一 RestTemplate是什么 RestTemplate是spring提供的Http协议实现类 也就是说导入spring boot starter web的项目可以直接使用RestTemplate类 就是基于模板方法设计模式的 封装了所
  • 租用高防服务器得必要

    租用高防服务器得必要 一 高防服务器的防御性 在网络恶意暴增的情况下 如何避免DDOS和CC 可以说是企业最为关注的问题 而防御因网络出现不整出运转等问题 最后就是选择高防服务器 高防服务器对于维护独立服务器的稳定性和拓展流量都有很大的帮助
  • 8-1运用指针比较三个数的大小

    include
  • springboot——helloworld入门

    springboot 简化spring开发 约定大于配置 提供完成restful的框架 注解 配置等完成 restful restful就是提供一堆标准的方法 例如get put等完成http的网站操作 helloworld入门 注解 Sp
  • windows下bitsandbytes安装报错解决

    RuntimeError CUDA Setup failed despite GPU being available Please run the following command to get more information pyth
  • c++ 构造

    include
  • ssh的实验室预约系统Python项目PHP程序Java安卓APP设计asp.net微信小程序

    文末获取联系方式 我们的毕设辅导团队由一群经验丰富 专业素质过硬的导师组成 他们来自于各个领域的专业人士 具备丰富的实践经验和深厚的学术背景 无论你的毕设是关于Python Java 小程序 asp net PHP nodejs还是其他领域
  • Matlab 生成license

    参考下面两个帖子 https ww2 mathworks cn matlabcentral answers 389888 matlab https www mathworks com matlabcentral answers 131749
  • 机器学习笔记 - 什么是模型量化压缩技术?

    一 简述 我们都知道现实世界是连续的状态 而计算机世界是离散的状态 这是什么意思呢 我们看一下下图 最右边的马力欧 高清 的状态 可以想象现实世界是连续的状态 而电脑世界在图像上呈现的是一格一格子的状态 左图 是离散的状态 所以在计算机世界
  • unordered_set unordered_multiset

    unordered set 名字 描述 insert 插入一个新元素 begin end 返回一个迭代器 指向第一个元素 最后一个元素后的理论元素 count 计算在无序集合容器中特定元素的出现次数 find 搜索元素 clear
  • 线程安全的问题以及解决方案

    线程安全 线程安全的定义 线程安全 某个代码无论是在单线程上运行还是在多线程上运行 都不会产生bug 线程不安全 单线程上运行正常 多线程上运行会产生bug 观察线程不安全 看看下面的代码 public class ThreadTest1
  • Android10.0 系统关于安兔兔显示信息的修改

    1 前言 在10 0的系统定制化开发中 在一些产品开发中 对于安兔兔等第三方检测工具 检测不出某些版本的内核信息等 显示0GB等问题的相关修改 由于不知道安兔兔的检测方式 所以就需要来修改 关于文本上的一些信息了 2 系统关于安兔兔显示信息
  • 打开游戏提示缺少(或找不到)XINPUT1_3.DLL怎么解决

    在电脑使用过程中 我们可能会遇到一些错误提示 其中之一就是xinput1 3 dll丢失 那么 xinput1 3 dll是什么文件 它对电脑有什么影响 本文将详细介绍xinput1 3 dll丢失的原因以及五个详细的解决方法 帮助大家解决
  • GPU深度学习性能的三驾马车:Tensor Core、内存带宽与内存层次结构

    编者按 近年来 深度学习应用日益广泛 其需求也在快速增长 那么 我们该如何选择合适的 GPU 来获得最优的训练和推理性能呢 今天 我们为大家带来的这篇文章 作者的核心观点是 Tensor Core 内存带宽和内存层次结构是影响 GPU 深度
  • 【华为OD机考 统一考试机试C卷】素数之积/RSA加密算法(C++ Java JavaScript Python)

    华为OD机考 统一考试 C卷 D卷 B卷 A卷 2023年11月份 华为官方已经将 华为OD机考 OD统一考试 A卷 B卷 切换到 OD统一考试 C卷 和 OD统一考试 D卷 根据考友反馈 目前抽到的试卷为B卷或C卷 D卷 其中C卷居多 按
  • Gson 自动生成适配器插件

    在json解析方面 我们常见有下面几方面困扰 1 moshi code gen能自动生成适配器 序列化效率比gson快 但是自定义程度不如gson 能java kotlin共存 且解决了默认值的问题 2 gson api 强大自由 但是 第