0

在解析其中一个服务调用的 JSON 响应时,我面临着一个典型的场景。

属性之一的内容(在下面的示例中,将“名称”视为属性)以 String 或 JSONObject 的形式出现。

如何通过代码处理这类场景。另外,请考虑 json 内容不必与同一组属性保持一致。

例子:

字符串响应

{"name":"Adam"}

JSON 响应

{"name":{"FirstName":"Adam", "MiddleName":"Don"} }

OR

{"name":{"FirstName":"Adam", "LastName":"Don"} }

OR

{"name":{"MiddleName":"Adam", "LastName":"Don"} }

4

4 回答 4

3

如果给定名称存在并且是 JsonObject,您可以JSONObject使用该方法要求根optJSONObject(name)返回给定名称。JSONObject否则,您也可以optString(name)使用字符串进行测试。

所以像:

JSONObject root = new JSONObject(... data from server ... );
JSONObject obj = root.optJSONObject("name");
if (obj != null) {
   // Do something with the object
} else {
   String name = root.getString("name");
   // Do something with the string
}
于 2013-08-06T06:09:58.293 回答
2

将您的响应 JSON 解析为 JSONObject,然后为“name”键获取另一个 JSONObject,如果它引发 JSONException,那么您的对象可能是一个字符串,以防万一您可以在 catch 块中为“name”键调用 get String。

String name = "";
JSONObject serverJSON = new JSONObject(YOUR_JSON_RESPONSE_STRING_FROM_SERVER);

try {
     JSONObject nameObject = serverJSON.getJSONObject("name");
     if (nameObject.has("first_name")) {
         name = nameObject.getString("first_name") + " ";
     }

     if (nameObject.has("middle_name")) {
         name += nameObject.getString("middle_name") + " ";
     }

     if (nameObject.has("last_name")) {
         name += nameObject.getString("last_name");
     }

     name = name.trim();
} catch (JSONException e) {
     // Probably a String, try again...
     try { 
          name = serverJSON.getString("name");
     catch (JSONException e) {
          // Not a String or a JSONObject... figure out what's wrong...
          e.printStackTrace();
     }
}

不过,我真的建议,如果您对服务器有任何控制权,请确保名称键选择一种类型并坚持使用它;一个 JSONObject... 您可以在 if 语句中使用 has(String key) 成员函数来正确查找所有数据,而无需知道运行时存在什么...

编辑:想到了一个不同的想法......将字符串解析为第一个冒号,看看下一个非空白字符是否是引号,如果是,那么你的键属于字符串,如果是花括号,那么它是一个 JSONObject。(如果两者都不是,那么你有一个错误,因为你不期望一个数组或数字或 null 或其他任何东西......)

boolean jsonIsString = true;
String searchString = json.substring(json.indexOf(":")).trim();
if ("{".equals(searchString.charAt(0)) {
    jsonIsString = false;
}
于 2013-08-06T05:42:23.173 回答
1

Tonity 的解决方案很好。您也可以使用此解决方案。

在我的解决方案中,在JSON 错误之前不会触发任何异常。我正在做的是跟随。

  1. 在字符串中搜索“:”的数量。
  2. 如果它返回 1,那么我们确定存在“名称”值。
  3. 否则,我们需要检查字符串中是否存在“FirstName”、“MiddleName”或“LastName”。

只需浏览此代码段,您就会找到解决问题的方法。

// String str = "{\"name\":\"chintan\"}";
String str = "{\"name\":{\"FirstName\":\"Chintan\",\"LastName\":\"Rathod\"}}";

try {
    //we will check how many ":" are there in string, if it is one, then
    // we are going to get "name" field.
    if ((str.split(":").length - 1) == 1) 
    {
        Log.d("Home", "1");
        JSONObject json = new JSONObject(str);
        Log.d("Home", "Name : " + json.get("name"));
    } 
    else
    {
        Log.d("Home", "more then 2");

        JSONObject jName = new JSONObject(str);

        JSONObject jTemp = jName.getJSONObject("name");

        if (jTemp.toString().contains("FirstName"))
            Log.d("Home", "FirstName :" + jTemp.getString("FirstName"));

        if (jTemp.toString().contains("MiddleName"))
            Log.d("Home","MiddleName :" +jTemp.getString("MiddleName"));

        if (jTemp.toString().contains("LastName"))
            Log.d("Home", "LastName :" + jTemp.getString("LastName"));
    }
} catch (JSONException e) {
    e.printStackTrace();
}

输出

08-06 11:52:34.060: D/Home(1439): more then 2
08-06 11:52:34.060: D/Home(1439): FirstName :Chintan
08-06 11:52:34.070: D/Home(1439): LastName :Rathod
于 2013-08-06T06:10:12.713 回答
1

我也遇到过这样的问题。我不想手动解析 JSON。如果firstName存在则执行此操作,否则执行此操作。我不想弄乱我的结构,因为我只定义 java 对象,而我的客户端处理解析。所以,我想出了以下内容:

@Getter
@Setter
@ToString
class Response {
    private Name name;

    @Getter
    @Setter
    @NoArgsConstructor
    @ToString
    public static class Name {
        private String name;
        private String firstName;
        private String middleName;
        private String lastName;

        public Name(String name) {
            this.name = name;
        }
    }
}

然后,解析json;

ObjectMapper objectMapper = new ObjectMapper();
Response response = objectMapper.readValue(json, Response.class);

现在,字符串响应和 JSON 响应可以用同一个类进行解析。

于 2018-06-13T13:49:46.430 回答