一. 前言

在开发过程中经常遇到json解析和生成的问题,所以用自己也一直用fastjson来实现这个功能。

但是,最近遇到一个问题:

  1. json字符串里面的数据很多都是"_"下划线的比如,op_id。

  2. 而在java里面,很多都是驼峰的写法,如opId

那这两种可以匹配然后解析吗?

二. http请求的解决方法

http请求有个@JsonProperty的注解,但是这个注解,fastjson不识别;不过fastjson支持JSONField注解,如下:

1
2
@JSONField(name="sta")
private String status;

三. 智能匹配

fastjson提供了智能匹配的规则,下面写法会自动映射

op_id->opid->ipId

也就是说就算json字符串是'op_id',那java变量也可以用opid或者opId,然后也可以获取相应的数据。

如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Runme {
    static int ONE_DAY_SECONDS = 24 60 60 1000;
    public static void main(String[] args) {
        String json = "{\"op-id\":1000}";
        Mo mo = JSON.parseObject(json, Mo.class);
         
        System.out.println(mo.getOpId());
    }
     
    public static class Mo {
        private String opId;
        public String getOpId() {
            return opId;
        }
        public void setOpId(String opId) {
            this.opId = opId;
        }
    }
}

四. 原理分析

那fastjson是怎么做到的呢?

看了下源代码

https://github.com/alibaba/fastjson

发现它的逻辑如下:

文件:src/main/java/com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java

方法:  smartMatch(String key, int[] setFlags)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public FieldDeserializer smartMatch(String key, int[] setFlags) {
        if (key == null) {
            return null;
        }
         
        FieldDeserializer fieldDeserializer = getFieldDeserializer(key, setFlags);
        if (fieldDeserializer == null) {
            long smartKeyHash = TypeUtils.fnv1a_64_lower(key);
            if (this.smartMatchHashArray == null) {
                long[] hashArray = new long[sortedFieldDeserializers.length];
                for (int i = 0; i < sortedFieldDeserializers.length; i++) {
                    hashArray[i] = TypeUtils.fnv1a_64_lower(sortedFieldDeserializers[i].fieldInfo.name);
                }
                Arrays.sort(hashArray);
                this.smartMatchHashArray = hashArray;
            }
            // smartMatchHashArrayMapping
            int pos = Arrays.binarySearch(smartMatchHashArray, smartKeyHash);
            boolean is = false;
            if (pos < 0 && (is = key.startsWith("is"))) {
                smartKeyHash = TypeUtils.fnv1a_64_lower(key.substring(2));
                pos = Arrays.binarySearch(smartMatchHashArray, smartKeyHash);
            }
            if (pos >= 0) {
                if (smartMatchHashArrayMapping == null) {
                    short[] mapping = new short[smartMatchHashArray.length];
                    Arrays.fill(mapping, (short) -1);
                    for (int i = 0; i < sortedFieldDeserializers.length; i++) {
                        int p = Arrays.binarySearch(smartMatchHashArray
                                , TypeUtils.fnv1a_64_lower(sortedFieldDeserializers[i].fieldInfo.name));
                        if (p >= 0) {
                            mapping[p] = (short) i;
                        }
                    }
                    smartMatchHashArrayMapping = mapping;
                }
                int deserIndex = smartMatchHashArrayMapping[pos];
                if (deserIndex != -1) {
                    if (!isSetFlag(deserIndex, setFlags)) {
                        fieldDeserializer = sortedFieldDeserializers[deserIndex];
                    }
                }
            }
            if (fieldDeserializer != null) {
                FieldInfo fieldInfo = fieldDeserializer.fieldInfo;
                if ((fieldInfo.parserFeatures & Feature.DisableFieldSmartMatch.mask) != 0) {
                    return null;
                }
                Class fieldClass = fieldInfo.fieldClass;
                if (is && (fieldClass != boolean.class && fieldClass != Boolean.class)) {
                    fieldDeserializer = null;
                }
            }
        }
        return fieldDeserializer;
    }

它里面有个重要的地方就是调用TypeUtils.fnv1a_64_lower(String)方法,分别计算传入的key(op_id)和定义的java成员变量opId,然后计算他们是否匹配。

如果匹配的话,就会覆盖。

所以,关键就在于TypeUtils.fnv1a_64_lower(String)方法实现,如下:

这个方法就是如果是'_'或者'-',那么就忽略,也就是如果是op_id,那么就会变成opid。

如果是大写,那么就转换成小写,也就是opId,就会变成opid。

所以op-id或者op_id,都可以匹配opId或者opid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static long fnv1a_64_lower(String key){
        long hashCode = 0xcbf29ce484222325L;
        for(int i = 0; i < key.length(); ++i){
            char ch = key.charAt(i);
            if(ch == '_' || ch == '-'){
                continue;
            }
            if(ch >= 'A' && ch <= 'Z'){
                ch = (char) (ch + 32);
            }
            hashCode ^= ch;
            hashCode *= 0x100000001b3L;
        }
        return hashCode;
    }

本文转自rongwei84n 51CTO博客,原文链接:http://blog.51cto.com/483181/1981575,如需转载请自行联系原作者

42. fastjson处理下划线和驼峰问题的方法和源码分析相关推荐

  1. fastjson 转下划线_42. fastjson处理下划线和驼峰问题的方法和源码分析

    一. 前言 在开发过程中经常遇到json解析和生成的问题,所以用自己也一直用fastjson来实现这个功能. 但是,最近遇到一个问题: json字符串里面的数据很多都是"_"下划线 ...

  2. python 下划线转驼峰

    # 下划线转驼峰 def str2Hump(text):arr = filter(None, text.lower().split('_'))res = ''j = 0for i in arr:if ...

  3. 下划线转驼峰,并且首字母大写

    下划线转驼峰,并且首字母大写 public String lineToHump(String str) {Pattern linePattern = Pattern.compile("_(\ ...

  4. springboot接口入参下划线转驼峰以及返回参数驼峰转下划线实现

    转自:springboot接口入参下划线转驼峰以及返回参数驼峰转下划线实现 - 李东平|一线码农 - 博客园 (cnblogs.com) 1.背景 在实际开发中,通常来说java里面是使用驼峰的命名规 ...

  5. idea 下划线字段转驼峰_Java如何实现数据库中表字段的下划线和驼峰式命名的Model相互转换,很方便的...-Go语言中文社区...

    其实通过逆向工程,然后去配置一些config,就可以实现,从Table到Model的相互转换,而且,对于下划线命名的Table字段,实现驼峰式命名的Model ,有时候我们只是做个测试,或者自己基于数 ...

  6. 在线下划线转驼峰,驼峰转下划线工具

    在线下划线转驼峰,驼峰转下划线工具 在线下划线转驼峰,驼峰转下划线工具 本工具可以将字符串下划线转为驼峰,或驼峰转下划线,纯客户端计算. 骆驼式命名法(Camel-Case)又称驼峰式命名法,是电脑程 ...

  7. springboot多数据源配置导致mybatis的下划线转驼峰命名不起作用

    今天在开发的时候,突然发现一个sql的下划线转驼峰命名没有起作用导致数据查询出现错误.具体如下: 之前一直都是在application.properties里面加上mybatis.configurat ...

  8. 手写:下划线转为驼峰命名法

    驼峰命名法: 命名由首字母小写,后面由首字母大写的一些词块组成 实现将'_'转为驼峰命名法 例如 a_tst 转为 aTest 1.正则表达式(仍有缺陷,待完善) <script>func ...

  9. 驼峰转下划线下划线转驼峰

    1.驼峰转下划线 private String humpToLine(String str) {Pattern humpPattern = Pattern.compile("[A-Z]&qu ...

最新文章

  1. 如何在MacOS上创建第一个iOS Flutter应用
  2. python中打印zip()函数结果和zip()函数的使用
  3. linux管理员常用的命令分享
  4. codeforces 1017E
  5. 从头到尾彻底理解傅里叶变换算法(上)
  6. oracle昨日时间,。。今日,昨日,上周,本月,本年,按时间统计总金额
  7. 淘宝网手机客户端开发(一)目录篇
  8. 子类既要实现接口又要继承抽象类的一个demo
  9. nginx 超时设置_Nginx最详细的反向代理配置步骤,拿去不谢
  10. 基于原生javascript的淡入淡出函数封装(兼容IE)
  11. 四款常见IT自动化运维工具简单介绍-行云管家
  12. 大黄蜂vep视频转成MP4格式提取工具的使用
  13. 画法几何,工程制图基础.....多角度平面投影图推断立体空间结构,实际距离的判别等
  14. 【图像处理】镜头去污渍(未完全实现):python + OpenCV
  15. mysql报表服务器配置_Power Bi报表服务器安装及数据库配置方法
  16. 【转】跨终端实践-天猫试戴的解决方案
  17. 《程序员》7月刊推荐:社交网数据库技术分析
  18. Ubuntu部署TeamTalk文档
  19. 2022年计算机考研408考点清单(1.0版本已更完——欢迎指正)
  20. 华云数据蝉联中国大数据50强 入选《2022数字化转型生态建设百佳案例》

热门文章

  1. ib_logfile 在数据库中有何作用?
  2. 判断链表是否存在环(及其延伸)
  3. Ajax Toolkit 控件学习系列(13) ——FilteredTextBoxExtender 控制输入
  4. Python脱产8期 Day02
  5. 微服务实战之春云与刀客(三)—— 面向接口调用代码结构实例
  6. redhat enterprise linux 下配置本地yum源
  7. vs code vue模板创建
  8. Java 读取 dwg 转换 dxf
  9. java 调用webservice的各种方法总结
  10. ISA2006标准版,本地主机不能上网问题的解决一例