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

简介:

一. 前言

在开发过程中经常遇到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,如需转载请自行联系原作者




相关文章
|
Go
Golang 语言该用命名返回值吗?
Golang 语言该用命名返回值吗?
53 0
|
9月前
|
JSON Java fastjson
Java【问题 06】一次解决JSON.toJSONString和@RestController首字母大小写问题(特指属性首字母大写变小写)
Java【问题 06】一次解决JSON.toJSONString和@RestController首字母大小写问题(特指属性首字母大写变小写)
716 0
|
程序员 Ruby
“茴” 字的六种写法---l 类方法的七种定义方式
“茴” 字的六种写法---l 类方法的七种定义方式
|
Java
Java实现驼峰、下划线互相转换
Java实现驼峰、下划线互相转换
975 1
34.从入门到精通:Python3 正则表达式检索和替换 repl 参数是一个函数 正则表达式对象 正则表达式修饰符 - 可选标志 正则表达式模式* 正则表达式实例
34.从入门到精通:Python3 正则表达式检索和替换 repl 参数是一个函数 正则表达式对象 正则表达式修饰符 - 可选标志 正则表达式模式* 正则表达式实例
|
Java
java中驼峰命名和下划线命名互转方法(代码实现)
1 /** 2 * 将驼峰式命名的字符串转换为下划线大写方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。 3 * 例如:HelloWorld->HELLO_WORLD 4 * @param name 转换前的驼峰式命名的字符串 5 * @return 转换后下划线大写方...
7844 0
|
IDE 开发工具 C语言
RxJava操作符详解--来看看你还记得多少
RxJava已经出现很多个年头了,但是依然被很多公司使用,如果现在还对RxJava了解的不够透彻, 可以看这个系列对它的分析:相信看完后你对它会有个更全面的认识。 这个系列主要从下面几个方面来讲解: **RxJava基本操作符使用** **RxJava响应式编程是如何实现的** **RxJava的背压机制及Flowable是如何实现背压的** **RxJava的线程切换原理**
|
Python
Python:case-convert命名规则转换和命名风格:驼峰、蛇形、帕斯卡
Python:case-convert命名规则转换和命名风格:驼峰、蛇形、帕斯卡
358 0
Python:case-convert命名规则转换和命名风格:驼峰、蛇形、帕斯卡
|
Java
|
Java
Java通用方法 -- 全角半角切换
全角字符切换半角字符
289 0

热门文章

最新文章