我有如下所示的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是从外部传入我的应用程序的,因此内容在时间上可能会非常不同。说它可以完全为空,或者某些元素可以为空,或者数组大小可以为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
}
在这种情况下,请提出是否有充分理由提出条件,而不是尝试-catch-记录并继续。
在这种情况下,如果使用JSONException有任何“优点”,您还可以分享吗?
答案 0 :(得分:1)
我认为这太令人费解了,尤其是随着链条越来越长。我会考虑一个远程类似解决方案的唯一情况是,用户是否需要确切地知道问题出在哪一点,并且有特定的准则来解决该问题以及在非常特定的用例中可能如何发生,但是在那种情况下情况下,您需要大量的if语句和log语句。
确实可以进行尝试捕获,但是您需要确保捕获不存在JSON字段或类型错误的JSON时可能发生的所有可能的异常,例如ClassCastException和NullPointerException。它很短,但不是很优雅,正如另一个回答者所说的那样,它可能隐藏其他异常(但您仍然可以记录堆栈跟踪)。
另一个选择是找到允许您使用Java 8 Optional类型的库。例如,建议使用Jackson。这更优雅,但也可能成为大型连锁店。同样,这也会给您的项目增加一个依赖性。
第三个选择是使用路径表达式JsonPath,在这里您可以将所有语句放入一个表达式中并获得所有结果。我认为这是完美的用例,也是迄今为止最好的解决方案。唯一的缺点是,这给您的项目增加了一个依赖性。
答案 1 :(得分:1)
在这种情况下,请提出是否有充分理由提出条件,而不是尝试-catch-记录并继续。
以下是两个原因:
效率:创建,引发和捕获异常是相对昂贵的。取决于版本的价格到底有多高,也许还取决于上下文。在最新版本中,JIT编译器(AFAIK)可以将某些序列优化为条件分支。但是,如果要记录异常,那么JVM将必须创建一个异常对象并填充stacktrace,这是最昂贵的部分。
如果您将NullPointerException
登录为:
json.getJSONObject("c").getJSONArray("f").getJSONObject(1).getString("b")
您可能无法分辨出哪些组件丢失或为空。 stacktrace中的行号不足以区分情况。 (使用JSONException
时,异常消息将为您提供更多线索。)
您也无法区分json
是null
的情况,这可能是另一种问题。即一个错误。如果您将其视为数据错误,则将很难找到并修复代码错误。
如果您捕获到所有所有异常(如另一个答案所建议),则可能隐藏了更多类别的错误。好主意。
在这种情况下,如果使用JSONException有任何“优点”,您还可以分享吗?
唯一真正的“专业”是它的代码可能更少,特别是如果您可以在许多此类代码中放置 try ... catch 。
最重要的是,您需要自己权衡一下。一个因素是,您获得与代码预期不符的JSON的可能性有多大。这将部分取决于产生JSON的内容。
答案 2 :(得分:1)
由于上面的回答,下面是解决问题的方法。
JSONPath在我提到的场景中表现最好。感谢@Konrad。
首先创建一个 com.jayway.jsonpath.Configuration
类型的配置对象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")
现在,性能也达到最佳。之所以花费更多的时间和内存是因为