jsonobject.parseobject是什么呢?不知道的小伙伴来看看小编今天的分享吧!
一、JSON.parseObject是fastjson中的方法,fastjson 是一个性能很好的Java语言实现的JSON解析器和生成器,来自阿里巴巴的工程师开发。其主要特点是:
1、快速:fastjson采用独创的算法,将parse的速度提升到极致,超过所有基于Java的json库,包括曾经号称最快的jackson;
2、强大:Fastjson完全支持http://json.org的标准(也是Google官方网站收录的参考实现之一);支持各种JDK类型;包括基本类型、JavaBean、Collection、Map、Enum、泛型等;
3、零依赖:没有依赖其它任何类库除了JDK,能够直接运行在Java SE 5.0以上版本;支持Android;开源 (Apache 2.0)。
二、parseObject(String str)的作用:
JSON.parseObject(String str)是将str转化为相应的JSONObject对象,其中str是“键值对”形式的json字符串,转化为JSONObject对象之后就可以使用其内置的方法,进行各种处理了。
三、FastJson对于JSON格式字符串、JSON对象及JavaBean之间的相互转换:
1、result格式:
{
"success":"true",
"returnAddress":"123"
}
JSONObject jsonObject=JSON.parseObject(result); //转换成object
jsonObject.getString("returnAddress") //获取object中returnAddress字段;
2、result格式:
{
"success":"true",
"data":{
"shop_uid":"123"
}
}
JSONObject shop_user =JSON.parseObject(result);
JSON.parseObject(shop_user.getString("data")).getString("shop_uid")
3、result格式:
{
"success":"true",
"data":[{
"shop_uid":"123"
},
{
"shop_name":"张三"
}]
}
JSONArray detail = JSON.parseArray(result);
for (int i=0; i<detail.size();i++){
if(detail.get(i)!=null||!detail.get(i).equals("")){
JSONArray detailChild =detail.getJSONArray(i);
if(detailChild.getInteger(1)>Integer.valueOf(ship.get("shiptime").toString())){
ship.put("shiptime",detailChild.getInteger(1));
ship.put("desc",detailChild.getString(0));
}
}
}
JSON转javaBean
1.1 JSONobject=>javaBean
JSONObject contentChild = contentsArray.getJSONObject(i);
QCCustomerScore.CustomerCore customerCore = JSON
.toJavaObject(contentChild, QCCustomerScore.CustomerCore.class);
1.2 String转javaBean
以上就是小编今天的分享了,希望可以帮助到大家。
浅谈Gson和fastjson使用中的坑
1.前言
相信大家在代码编写中都用过Gson和fastjson吧,用来进行 Java对象和json字符串之间的转换。
本篇文章就主要介绍博主在工作中使用这两款工具时遇到的坑和对应的解决办法。
觉得有用的可以点个赞哈~
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转换工具的问题,但两款工具确实各有各的优势,我觉得选择适合自己业务代码的就是最好的,这些问题也都能解决,也不是用不了,还是看解决方法而已,遇到的这些问题我都会记录下来,等以后碰到类似问题了就能直接解决,这样也不错。