首頁 > 軟體

關於JSON解析中獲取不存在的key問題

2022-07-06 14:05:34

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;
    }

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com