43. fastjson处理下划线和驼峰问题的方法和源码分析
一. 前言 在开发过程中经常遇到json解析和生成的问题,所以用自己也一直用fastjson来实现这个功能。 但是,最近遇到一个问题:
那这两种可以匹配然后解析吗? 二. http请求的解决方法 http请求有个@JsonProperty的注解,但是这个注解,fastjson不识别。 三. 智能匹配 fastjson提供了智能匹配的规则,下面写法会自动映射 op_id->opid->ipId 也就是说就算json字符串是'op_id',那java变量也可以用opid或者opId,然后也可以获取相应的数据。 如下: publicclassRunme{ staticintONE_DAY_SECONDS=24*60*60*1000; publicstaticvoidmain(String[]args){ Stringjson="{"op-id":1000}"; Momo=JSON.parSEObject(json,Mo.class); System.out.println(mo.getOpId()); } publicstaticclassMo{ privateStringopId; publicStringgetOpId(){ returnopId; } publicvoidsetOpId(StringopId){ this.opId=opId; } } } 四. 原理分析 那fastjson是怎么做到的呢? 看了下源代码 https://github.com/alibaba/fastjson 发现它的逻辑如下: 文件:src/main/java/com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java 方法: smartMatch(String key,int[] setFlags) publicFieldDeserializersmartMatch(Stringkey,int[]setFlags){ if(key==null){ returnnull; } FieldDeserializerfieldDeserializer=getFieldDeserializer(key,setFlags); if(fieldDeserializer==null){ longsmartKeyHash=TypeUtils.fnv1a_64_lower(key); if(this.smartMatchHashArray==null){ long[]hashArray=newlong[sortedFieldDeserializers.length]; for(inti=0;i<sortedFieldDeserializers.length;i++){ hashArray[i]=TypeUtils.fnv1a_64_lower(sortedFieldDeserializers[i].fieldInfo.name); } Arrays.sort(hashArray); this.smartMatchHashArray=hashArray; } //smartMatchHashArrayMapping intpos=Arrays.binarySearch(smartMatchHashArray,smartKeyHash); booleanis=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=newshort[smartMatchHashArray.length]; Arrays.fill(mapping,(short)-1); for(inti=0;i<sortedFieldDeserializers.length;i++){ intp=Arrays.binarySearch(smartMatchHashArray,TypeUtils.fnv1a_64_lower(sortedFieldDeserializers[i].fieldInfo.name)); if(p>=0){ mapping[p]=(short)i; } } smartMatchHashArrayMapping=mapping; } intdeserIndex=smartMatchHashArrayMapping[pos]; if(deserIndex!=-1){ if(!isSetFlag(deserIndex,setFlags)){ fieldDeserializer=sortedFieldDeserializers[deserIndex]; } } } if(fieldDeserializer!=null){ FieldInfofieldInfo=fieldDeserializer.fieldInfo; if((fieldInfo.parserFeatures&Feature.DisableFieldSmartMatch.mask)!=0){ returnnull; } ClassfieldClass=fieldInfo.fieldClass; if(is&&(fieldClass!=boolean.class&&fieldClass!=Boolean.class)){ fieldDeserializer=null; } } } returnfieldDeserializer; } 它里面有个重要的地方就是调用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 publicstaticlongfnv1a_64_lower(Stringkey){ longhashCode=0xcbf29ce484222325L; for(inti=0;i<key.length();++i){ charch=key.charAt(i); if(ch=='_'||ch=='-'){ continue; } if(ch>='A'&&ch<='Z'){ ch=(char)(ch+32); } hashCode^=ch; hashCode*=0x100000001b3L; } returnhashCode; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 使用closedXML C#库,如何在尝试保存时找出导致此错误的数据
- c – 当QMenu触发一个QAction时,防止QMenu关闭
- 帮助理解Ruby中的yield和枚举器
- Ruby是否具有与未定义的实例变量相当的method_missing?
- c# – 将大文件添加到IO.Compression.ZipArchiveEntry会抛出
- 模式匹配 – 未解析的flex记录(需要知道此上下文中所有字段
- c# – Task.Run与直接异步调用,用于启动长时间运行的异步方
- objective-c – 用NSOperationQueue解决读写器问题?
- c – 在boost python中使用自定义智能指针
- c# – 在列表框中指定ItemContainer的datacontext类型