我正在解析一个大的JSONArray
(大约33000项)JSON对象。我正在我的应用程序中将JSON对象转换为我自己的对象。它看起来有点像:
Card card = Card.build(cardObj.getString("name"))
.setFoo(cardObj.getString("foo"))
.setBar(cardObj.getInt("bar"))
.setBaz(cardObj.getString("baz"))
... about 10 more
问题是所有卡(在原始JSON中)没有相同的密钥。因此,我必须为我的解析器中的每一行代码都设置一个try catch块,因为在代码可以继续执行之前必须处理任何异常。例如,如上面的代码片段所示,如果我正在解析一个没有bar
的对象,那么代码将立即跳转到异常处理,跳过它设置{{1}的步骤}值。
我的问题:有没有办法做到这一点,我可以避免尝试捕捉每一行?我知道你不能忽略异常,但也许有类似的东西可能有所帮助。
更好的例子
baz
如果代码在设置try {
Card card = Card.build(cardObj.getString("name"))
.setFoo(cardObj.getString("foo"))
.setBar(cardObj.getInt("bar"))
.setBaz(cardObj.getString("baz"))
} catch (JSONException e) {
// The code will jump here for any exception.
}
或foo
时失败,则执行上下文将跳转到catch块内的错误处理步骤。在违规行之后的函数调用将永远不会运行,因此可能永远不会设置bar
或bar
,即使它们存在于原始JSON中。除了尝试捕获每一行或检查以确保每个值都预先存在之外,我无法阻止这种情况。有没有更好的方法呢?
答案 0 :(得分:1)
这不是你的问题的解决方案,但无论如何,当你有一些像Gson这样的漂亮的库时,你为什么要编写一百行代码来解析JSON呢?
它很容易使用这个库,你所要做的就是编写一个POJO类,在其中解析你的JSON。
是的,如果您的JSON架构中没有某些JSON密钥,您也不必担心这一点。 Gson也处理这个案子。例如,让我参加像这样的POJO课程。
public class Parsed {
public String name;
public String foo;
public Integer bar;
public String baz;
}
现在,如果在您的JSON中,foo
密钥不可用,那么在使用Gson解析您的JSON时,它将被分配给null
。因此,从代码中只需检查值是否为null,同时将其分配给其他变量。就是这样。
答案 1 :(得分:1)
如果你的JSON库有办法处理默认值我强烈建议使用它并传递null
或任何好的足够的默认值。
该方法可能类似于jsonObject.getString(String key, String defaultValue)
。
但是如果您的JSON库没有为您提供使用默认值的方法,您可以将每个getXXX()
调用包装在方法中,该方法负责处理这样的异常:
String getOrDefault(JSONObject obj, String key, String defValue) {
try {
String value = obj.getString(key);
return value;
}
catch (Exception ex) {
return defValue;
}
}
// similary create functions for all data types.
然后在构建器部分使用:
Card card = Card.build(getOrDefault(cardObj, "name", null))
... about 10 more
答案 2 :(得分:0)
在执行JSONObject
之前,只需检查getSomething
是否包含对象(类型正确)。 JSONObject
实现了地图 - https://docs.oracle.com/javaee/7/api/javax/json/JsonObject.html
此外,JsonArray
实施List<JsonValue>
https://docs.oracle.com/javaee/7/api/javax/json/JsonArray.html
例如,在致电cardObj.getString("foo")
致电cardObj.containsKey("foo")
之前。然后您可以考虑检查值类型:
JsonValue value=cardObj.get("foo");
if (value.getValueType()=!JsonValue.ValueType.STRING) {
//do something reasonable for invalid type.
}
您可以考虑使用更高抽象级别的库。使用Jackson时,对于不存在的json标记将不执行任何操作(Card
对象中的匹配字段将保持为空。)
使用Jackson时,反序列化就是调用
的问题Card card=new ObjectMapper().readValue("jsonString",Card.class);
答案 3 :(得分:0)
我在这里看到两个选项。
cardObj
之前验证Card
,这可能需要编写大量无聊的代码。Card
对象创建 - 允许使用无效数据创建它,然后通过实现getValidationErrors
方法进行验证,该方法将返回错误集合,其中包含哪些字段失败的详细信息。 JSR303注释和验证器也适合这里。