解析JSONObjects时的异常处理

时间:2017-06-24 20:22:25

标签: java json

我正在解析一个大的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块内的错误处理步骤。在违规行之后的函数调用将永远不会运行,因此可能永远不会设置barbar,即使它们存在于原始JSON中。除了尝试捕获每一行或检查以确保每个值都预先存在之外,我无法阻止这种情况。有没有更好的方法呢?

4 个答案:

答案 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)

我在这里看到两个选项。

  1. 在创建cardObj之前验证Card,这可能需要编写大量无聊的代码。
  2. 放松Card对象创建 - 允许使用无效数据创建它,然后通过实现getValidationErrors方法进行验证,该方法将返回错误集合,其中包含哪些字段失败的详细信息。 JSR303注释和验证器也适合这里。