关于JSON解析中获取不存在的key问题

 更新时间:2022年07月06日 10:44:03   作者:BlueKitty1210  
这篇文章主要介绍了关于JSON解析中获取不存在的key问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

1 . fastjson

在fastjson中有些getXXX方法 , 如getString , getInteger , getIntValue等 , 当调用getXXX方法时 , 如果传入的key在json中不存在 , 那调用这些方法会报错抛出异常吗 ?

首先来看代码demo

public static void main(String[] args) {
    String str = "{\"name\":\"Bob\",\"age\":\"18123\"}";
    JSONObject jsonObject = JSON.parseObject(str);
    String[] keys = { "age" ,   "score"};
    for(String key : keys){
		System.out.println(jsonObject.getString(key));
		System.out.println(jsonObject.getInteger(key));
		System.out.println(jsonObject.getIntValue(key));
    }
}

运行结果如下 : 

18123
18123
18123
null
null
0

可看到 , 对不存在的key值(score)尝试进行getXXX时 , 会返回当前类型的默认值(String返回null , Integer返回null , intValue返回0)

查看getString/getInteger源码如下 : 

public String getString(String key) {
    Object value = get(key);
    if (value == null) {
        return null;
    }
    return value.toString();
}
public Integer getInteger(String key) {
   Object value = get(key);	
   return castToInt(value);
}
  • getString就是调用get方法 , 然后判断为null , 为null则返回null , 否则调用对象的toString()方法.
  • getInteger就是相当于调用get方法 , 然后调用castToInt方法将Ojbect对象转换为Integer对象 , castToInt方法如下 : 
public static Integer castToInt(Object value) {
    if (value == null) {
        return null;
    }
 
    if (value instanceof Integer) {
        return (Integer) value;
    }
 
    if (value instanceof Number) {
        return ((Number) value).intValue();
    }
 
    if (value instanceof String) {
        String strVal = (String) value;
 
        if (strVal.length() == 0 //
            || "null".equals(strVal) //
            || "NULL".equals(strVal)) {
            return null;
        }
        
        if (strVal.indexOf(',') != 0) {
            strVal = strVal.replaceAll(",", "");
        }
 
        return Integer.parseInt(strVal);
    }
 
    if (value instanceof Boolean) {
        return ((Boolean) value).booleanValue() ? 1 : 0;
    }
 
    throw new JSONException("can not cast to int, value : " + value);
}

首先看到第一个if中进行了判断 , 如果value值为null , 则直接返回null , 那getIntValue怎么判断的呢 , getIntValue源码如下 : 

public int getIntValue(String key) {
    Object value = get(key);
 
    if (value == null) {
        return 0;
    }
 
    return castToInt(value).intValue();
}

原来在调用castToInt之前 ,就先做了一次null的判断 , 为null直接返回了0 . 

那调用get方法获取一个不存在的key时 , 为什么会返回null而不是报错呢 , 查看get源码如下

public Object get(Object key) {
    return map.get(key);
}

map是JSONObject的一个成员变量

private final Map<String, Object> map;

原来 , JSONObject先将json字符串转换为了一个map , 而map的get方法获取不存在的key时 , 返回的就是null . 

由此可以看到 , fastjson对不存在的key做了判断 , 如果没有则会返回类型的默认值 . 

2 . net.sf.json

    public static void main(String[] args) {
        String str = "{\"name\":\"Bob\",\"age\":\"18\"}";
        JSONObject jsonObject = JSONObject.fromObject(str);
//        System.out.println(jsonObject.get("gender"));//null
//        System.out.println(jsonObject.getString("gender"));//JSONObject["gender"] not found
//        System.out.println(jsonObject.getInt("age"));//18
        System.out.println(jsonObject.getInt("score"));//JSONObject["score"] is not a number
 
    }

可以看到和fastjson的处理策略不同 , 它是对不存在的key抛出一个JSONException异常 , 查看源码可以看到

    public String getString(String key) {
        this.verifyIsNull();
        Object o = this.get(key);
        if (o != null) {
            return o.toString();
        } else {
            throw new JSONException("JSONObject[" + JSONUtils.quote(key) + "] not found.");
        }
    }
    public int getInt(String key) {
        this.verifyIsNull();
        Object o = this.get(key);
        if (o != null) {
            return o instanceof Number ? ((Number)o).intValue() : (int)this.getDouble(key);
        } else {
            throw new JSONException("JSONObject[" + JSONUtils.quote(key) + "] is not a number.");
        }
    }

3 . org.json

和net.sf.json一样 , org.json对不存在的key策略还是抛出异常 . 但org.json更加严格 , 在使用get("key")时就会直接抛出异常

    public static void main(String[] args) throws Exception {
        String str = "{\"name\":\"Bob\",\"age\":\"18\"}";
        JSONObject jsonObject = new JSONObject(str);
        System.out.println(jsonObject.get("gender"));//No value for gender
        System.out.println(jsonObject.getString("gender"));//No value for gender
        System.out.println(jsonObject.getInt("age"));//18
        System.out.println(jsonObject.getInt("score"));//No value for score
    }

get方法源码如下 : 

    public Object get(String name) throws JSONException {
        Object result = nameValuePairs.get(name);
        if (result == null) {
            throw new JSONException("No value for " + name);
        }
        return result;
    }

getString源码如下 , getInt与之类似 : 

    public int getInt(String name) throws JSONException {
        Object object = get(name);
        Integer result = JSON.toInteger(object);
        if (result == null) {
            throw JSON.typeMismatch(name, object, "int");
        }
        return result;
    }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • spring boot使用拦截器修改请求URL域名 换 IP 访问的方法

    spring boot使用拦截器修改请求URL域名 换 IP 访问的方法

    Spring Interceptor是一个非常类似于Servlet Filter 的概念 ,这篇文章主要介绍了spring boot使用拦截器修改请求URL域名 换 IP 访问的相关知识,需要的朋友可以参考下
    2022-09-09
  • Java 生成带Logo和文字的二维码

    Java 生成带Logo和文字的二维码

    这篇文章主要介绍了Java 生成带Logo和文字的二维码的方法,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-04-04
  • 解决redisTemplate向redis中插入String类型数据时出现乱码问题

    解决redisTemplate向redis中插入String类型数据时出现乱码问题

    这篇文章主要介绍了解决redisTemplate向redis中插入String类型数据时出现乱码问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • jpa 使用@Column来定义字段类型

    jpa 使用@Column来定义字段类型

    这篇文章主要介绍了jpa使用@Column来定义字段类型,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Java女装商城系统的实现流程

    Java女装商城系统的实现流程

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+SSM+jsp+mysql+maven实现一个女装商城系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • 使用mybatis插件PageHelper实现分页效果

    使用mybatis插件PageHelper实现分页效果

    这篇文章主要为大家详细介绍了使用mybatis插件PageHelper实现分页效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • Java Arrays.sort()如何实现对int类型数组倒序排序

    Java Arrays.sort()如何实现对int类型数组倒序排序

    这篇文章主要介绍了Java Arrays.sort()如何实现对int类型数组倒序排序问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • Java自定义标签用法实例分析

    Java自定义标签用法实例分析

    这篇文章主要介绍了Java自定义标签用法,结合实例形式分析了java自定义标签的定义、使用方法与相关注意事项,需要的朋友可以参考下
    2017-11-11
  • 深入探究Java线程的状态与生命周期

    深入探究Java线程的状态与生命周期

    在java中,任何对象都要有生命周期,线程也不例外,它也有自己的生命周期。线程的整个生命周期可以分为5个阶段,分别是新建状态、就绪状态、运行状态、阻塞状态和死亡状态
    2022-04-04
  • 教你怎么用java一键自动生成数据库文档

    教你怎么用java一键自动生成数据库文档

    最近小编也在找这样的插件,就是不想写文档了,浪费时间和心情啊,果然我找到一款比较好用,操作简单不复杂.screw 是一个简洁好用的数据库表结构文档的生成工具,支持 MySQL、Oracle、PostgreSQL 等主流的关系数据库.需要的朋友可以参考下
    2021-05-05

最新评论