[英]How to avoid JSONObject Null check
我有 JSON 如下所示
{
"a1": "aaa",
"b1": 333,
"c1": {
"c1": "ccc",
"d1": "ddd",
"f1": [
{"a1": "xyz"},
{"b1": "lmn"},
{"c1":123.00}
]
}
}
我正在將文件讀入 String 並創建一個 JSONObject 如下
JSONObject json = new JSONObject(new JSONTokener(str));
JSON 從外部進入我的應用程序,因此內容在時間上可能會有很大不同。 說它可以完全是 null 或者某些元素可以是 null 或者數組大小可以是 0 或 1 或更多等。
當我處理 JSONObject 時,我可以繼續使用檢查所有元素
json.has and !=null
這樣它就不會拋出任何異常。
我可以有如下代碼
if(
json.has("c")
&& json.getJSONObject("c")!= null
&& json.getJSONObject("c").has("f")
&& json.getJSONObject("c").getJSONArray("f").length() > 1
&&json.getJSONObject("c").getJSONArray("f").getJSONObject(1).has("b")
){
String x = json.getJSONObject("c").getJSONArray("f").getJSONObject(1).getString("b");
}
這使得代碼具有一長串 if 條件。
但是我在想,我可以用 try catch 來附上語句
try {
String x = json.getJSONObject("c").getJSONArray("f").getJSONObject(1).getString("b");
}catch(JSONException e) {
//log and proceed
}
請建議在這種情況下是否有任何正當理由放置一個較長的 if 條件,而不是僅僅嘗試 - 捕獲 - 記錄並繼續。
如果在這種情況下使用 JSONException 有任何“優點”,你也可以分享嗎?
我認為這太令人費解了,尤其是當鏈條變長時。 我會考慮遠程類似解決方案的唯一情況是,如果用戶需要確切地知道問題出在哪一點,並且有關於如何解決這個問題以及在非常具體的用例中如何發生這種情況的具體指導方針,但是在那個如果你需要大量的 if 語句和 log 語句。
正如您所建議的,Try-catch 確實是可能的,但是您需要確保捕獲在 JSON 字段不存在或類型錯誤時可能發生的所有異常,例如 ClassCastException 和 NullPointerException。 它很短但不是很優雅,正如其他回答者所說可能隱藏其他異常(但您仍然可以記錄堆棧跟蹤)。
另一種選擇是找到一個庫,允許您使用 Java 8 可選類型。 例如,建議使用Jackson 。 這更優雅,但也可以成為一個大鏈。 這也為您的項目增加了一個依賴項。
第三種選擇是使用路徑表達式JsonPath ,您可以將所有語句放入一個表達式中並獲得所有結果。 在我看來,這是一個完美的用例,也是迄今為止最好的解決方案。 唯一的缺點是這為您的項目增加了一個依賴項。
請建議在這種情況下是否有任何正當理由放置一個較長的 if 條件,而不是僅僅嘗試 - 捕獲 - 記錄並繼續。
這里有幾個原因:
效率:創建、拋出和捕獲異常相對昂貴。 究竟有多昂貴取決於版本,也可能取決於上下文。 在最近的版本中,JIT 編譯器可以 (AFAIK) 將一些序列優化為條件分支。 但是,如果您要記錄異常,那么 JVM 將不得不創建異常 object 並填充堆棧跟蹤,這是最昂貴的部分。
如果您將NullPointerException
記錄為:
json.getJSONObject("c").getJSONArray("f").getJSONObject(1).getString("b")
您可能無法分辨缺少哪些組件或 null。 堆棧跟蹤中的行號不足以區分這些情況。 (使用JSONException
異常消息將為您提供更多線索。)
您也無法區分json
是null
的情況,這可能是另一種問題; 即一個錯誤。 如果您將其視為數據錯誤,則很難找到和修復代碼錯誤。
如果您捕獲所有異常(如另一個答案所建議的那樣),您可能會隱藏更多類別的錯誤。 餿主意。
如果在這種情況下使用 JSONException 有任何“優點”,你也可以分享嗎?
唯一真正的“優點”是它可能需要更少的代碼,特別是如果你可以嘗試...捕獲很多這樣的代碼。
最重要的是,您需要自己權衡一下。 一個因素是您獲得不符合您的代碼預期的 JSON 的可能性有多大。 這將部分取決於生產 JSON 的產品。
感謝上面的回復,下面是問題的解決方法。
JSONPath最適合我提到的場景。 感謝@Konrad。
首先創建一個 com.jayway.jsonpath.Configuration 類型的配置object
Configuration conf = Configuration.builder().options(Option.SUPPRESS_EXCEPTIONS).mappingProvider(new JsonOrgMappingProvider()).jsonProvider(new JsonOrgJsonProvider()).build();
DocumentContext docContext = JsonPath.using(conf).parse(json);
如果我們使用默認提供程序,那么我們需要按如下方式解析 JSONObject
DocumentContext docContext = JsonPath.using(conf).parse(json.toString());
然后閱讀我使用的元素
docContext.read("$.a.b.c.d.values[0].e.f")
性能現在也是最佳的。 花費更多時間和 memory 的原因是因為
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.