您的位置 首页 php

浅谈Gson和fastjson使用中的坑


1.前言

2.Gson和fastjson介绍

Google Gson是一个简单的基于Java的库,用于将Java对象序列化为JSON,反之亦然。 它是由Google开发的一个开源库。

fastjson和Gson一样的作用,但其是由国内阿里巴巴开发的一款工具。

fastjson比Gson快很多倍,也由于其是国内阿里开发,被大量使用,但也频繁被爆出问题,官方也紧急修复更新版本了。但是实际使用中,这两款工具也各有各的坑,合理地根据自己需要的去选择工具即可。

3.问题说明及解决

下面将先说明我遇到的坑,然后会给出相应解决办法,当然大家可以摸索更好的解决方式~

3.1 Gson会将Integer类型转为Double

场景:一个业务需求的编辑功能,我需要把查询后得到的id隐藏在页面上,以便保存时根据id去修改数据。但自测时发现传到页面上的值是double类型,但数据库中是int,这就造成了无法修改的问题,一一排查问题后我发现是Gson搞的鬼

解决办法1:使用fastjson即可解决,引入依赖后代码使用如下(推荐):

 Map<String,Object> map = JSONObject.parseObject(result,Map.class);  

解决方法2:将对象中的Integer类型改成String类型,这样就不会被自动转换了(根据自己业务情况使用)

解决方法3:在定义Gson时直接定义类型,代码如下:

 private static Type typeToken = new TypeToken<TreeMap<String, Object>>(){}.getType();Gson gson = new GsonBuilder()            .registerTypeAdapter(                    new TypeToken<TreeMap<String, Object>>(){}.getType(),                    new JsonDeserializer<TreeMap<String, Object>>() {                        @Override                        public TreeMap<String, Object> deserialize(                                JsonElement json, Type typeOfT,                                JsonDeserializationContext context) throws JsonParseException {                             TreeMap<String, Object> treeMap = new TreeMap<>();                            JsonObject jsonObject = json.getAsJsonObject();                            Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();                            for (Map.Entry<String, JsonElement> entry : entrySet) {                                Object ot = entry.getValue();                                if(ot instanceof JsonPrimitive){                                    treeMap.put(entry.getKey(), ((JsonPrimitive) ot).getAsString());                                }else{                                    treeMap.put(entry.getKey(), ot);                                }                            }                            return treeMap;                        }                    }).create();  

实际代码中调用:

 Map<String, Object> params = gson.fromJson(result, typeToken);  

3.2 Gson不序列化匿名内部类

场景:完成任务接口时写了测试类来测接口,初始化Map集合的时候用了如下比较优雅的方式:

 Map<String, String> map = new HashMap<String, String>() {    {put("logNo", "123456");        put("reqTime", "20210607");    }};Gson gson = new Gson();System.out.println(gson.toJson(map));  

但是运行测试类输出结果以后会发现为null。这是因为此种方式生成的Map是匿名内部类的实例,也就是new出来的map没有类名。

查询相关文章可知:内部类的适配器会生成对外部类/实例的隐式引用,会导致循环引用。所以结论为:Gson不会序列化匿名内部类。

解决方法:使用fastjson就不会出现这种问题,可成功序列化转为json数据

看到这里是否觉得Gson出现的问题,fastjson都能解决,那下面就介绍下fastjson在实际应用中的坑。

3.3 fastjson会将数据顺序改变

场景:在对接其他公司接口时往往都需要加密解密并签名验签,为了防止传输过程中数据被篡改,主要是为了安全。此时json传输的数据顺序则是重要的,如果被打乱则会解密验签失败,我在用fastjson时就出现了这种问题,一度头疼~

解决方法1:解析返回数据时增加参数不调整顺序(推荐)

此时你的fastjson版本应该为1.2.3以上

 <dependency>            <groupId>com.alibaba</groupId>            <artifactId>fastjson</artifactId>            <version>1.2.3</version>        </dependency>  

然后在解析数据时增加 Feature.OrderedField 参数即可

 FrontJsonResponse frontJsonResponse = JSONObject.parseObject(response,FrontJsonResponse.class, Feature.OrderedField);  

解决方法2:使用Gson解析数据即可,不会改变数据顺序

 Gson gson = new Gson();FrontJsonResponse frontJsonResponse = gson.fromJson(response,FrontJsonResponse.class)  

3.4 fastjson会将字段首字母变为小写

场景:在对接其他公司接口时,文档中字段名称多为大写字母(如:FILE_NM等)如果自己想定义对象实体来序列化的话,使用fastjson就会在上送时将实体中每个属性的首字母变为小写(如:fILE_NM),这样上送则肯定会出问题,可以用以下方法解决:

解决方法1:在属性名加上 @JSONField(name = “”) 注解即可(推荐)

 @JSONField(name = "FILE_NM")private String FILE_NM;  

解决方法2:序列化时增加参数 new PascalNameFilter() ,会将首字母强制转换为大写。

 JSON.toJSONString(bean,new PascalNameFilter());  

3.5 fastjson不会将多层json转换为Map

场景:在对接第三方公司接口验签时,使用fastjson将返回数据转换为Map,再去生成待签名串验签时发现验签失败,查询后得知和第三方签名是生成的串不一致,因为处理方式不同,具体场景请看下面示例:

     public static void main(String[] args) {        String str = "{\"result\":{\"user_info\":{\"id\":14390753,\"sex\":1},\"complete_status\":0},\"errcode\":0}";        Map<String,Object> fastMap = JSONObject.parseObject(str, Map.class);        System.out.println("fastMap====="+fastMap);        Gson gson = new Gson();        Map<String,Object> gsonMap = gson.fromJson(str,Map.class);        System.out.println("gsonMap====="+gsonMap);    }  

以上代码输出结果为:

 fastMap====={result={"user_info":{"sex":1,"id":14390753},"complete_status":0}, errcode=0}gsonMap====={result={user_info={id=1.4390753E7, sex=1.0}, complete_status=0.0}, errcode=0.0}  

对比处理方式和实际结果就可以知道,如果json字符串里有多层json对象,使用fastjson时并不会处理里层的json,只会将外层json数据转换为Map,而使用Gson时会将符合json格式的数据都转换为Map。

最后跟第三方确认以后,因为他们不同接口有不同处理方式,我们这边只能兼容(因为他们改不了,怕影响别的使用方),根据不同接口去判断该用fastjson还是用Gson解析返回的数据再进行验签(真的…一言难尽…)

所以遇到这种情况时,要确定对方是以什么方式来处理,我们这边再确定用什么方式来接,这也是这两种工具的一个不同点。

4.总结

实际开发过程中遇到以上问题就很头疼,如果不一步一步debug看代码输出结果,根本不会想到是json转换工具的问题,但两款工具确实各有各的优势,我觉得选择适合自己业务代码的就是最好的,这些问题也都能解决,也不是用不了,还是看解决方法而已,遇到的这些问题我都会记录下来,等以后碰到类似问题了就能直接解决,这样也不错。

文章来源:智云一二三科技

文章标题:浅谈Gson和fastjson使用中的坑

文章地址:https://www.zhihuclub.com/50322.shtml

关于作者: 智云科技

热门文章

评论已关闭

30条评论

  1. Monitor plasma levels when used concomitantly Serious Use Alternative 1 carbamazepine will decrease the level or effect of ritonavir by affecting hepatic intestinal enzyme CYP3A4 metabolism

  2. 94 Hypogonadism reduction or absence of hormone secretion or other physiological activity of the gonads testes or ovaries 5 people, 6 PUBMED Abstract McDonald CC, Stewart HJ Fatal myocardial infarction in the Scottish adjuvant tamoxifen trial

  3. Spotlight Poster PD9 01 Expanding downstaging criteria in AJCC pathologic prognostic staging using Oncotype DX Recurrence Score assay in T1 2N0 hormone receptor positive patients enrolled in the TAILORx Trial

  4. Table 3 shows the incidence of sexual function adverse reactions that occurred in 2 of desvenlafaxine extended release tablets treated MDD patients in any fixed dose group

  5. 100 Caja x 21 tabs Migration studies were conducted in a 24 well plate with the transwell membrane coated with Growth Factor Reduced Matrigel 50 Ојl

  6. oh and lucie_cille was asking about progesterone not clomid Routine cbc and a baseline between the cardiovascular life expectancy

  7. These drugs are administered orally on a daily basis This may be especially important, because up to 31 of patients newly diagnosed with advanced HCC have hypertension, just less than 10 carry a diagnosis of cardiovascular ischemic heart disease, approximately 15 are diabetic, and approximately 11 have some form of chronic lung disease all of which could be exacerbated by treatment related toxicities

  8. After years of effort invested in encouraging mammography, to reverse course would cause widespread confusion and anger

  9. As well, PTX is regarded as an antagonist for adenosine 2 receptor A2R Hussien et al The issue raised by bigoted heterosexuals was that same sex marriage somehow taints or destroys marriage, when the truth is that the divorce rate in this country has already done a good job of tainting and destroying marriage

  10. Despite the presence of diluted urine, an increased and dose dependent total urinary sodium loss was observed in the first 24 hours of treatment in the tolvaptan treated patients

  11. Felbamate was found to produce testicular interstitial cell tumours in male rats McGee et al

  12. Borlaug BA, Melenovsky V, Russell SD, Kessler K, Pacak K, Becker LC, Kass DA Duration 8 weeks Dose Winny or Anavar 20 mg per day for the first four weeks and 25 mg per day for the next four weeks

  13. Serum level of E 2 at the time of hCG administration was significantly higher in those who were treated with CC when compared to control 1153

  14. cisplatin and isavuconazonium sulfate both decrease immunosuppressive effects; risk of infection

  15. Mice with pituitary tumors in which p27 Kip1 was reactivated p27 S S; CreER by tamoxifen showed normalization of the cell cycle regulators cyclin E2 and p18 Ink4c A handful of sea slugs of the order Sacoglossa are able to steal chloroplasts kleptoplasts from their algal food sources and maintain them functionally for periods rangin

  16. receptor tyrosine kinase translocation was reported in a follicular variant of the papillary thyroid

网站地图