【问题标题】:Java - Parsing JSON Response - Content is either String or JSONObjectJava - 解析 JSON 响应 - 内容是字符串或 JSONObject
【发布时间】:2013-08-07 00:08:01
【问题描述】:

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

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

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

例子:

字符串响应

{"name":"Adam"}

JSON 响应

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

OR

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

OR

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

【问题讨论】:

  • So.. 你想在 java 中解析 JSON 字符串??
  • 在上面的任何例子中,每个都是 JSON.. 你怎么说 {"name":"Adam"} 是字符串
  • 您到底在寻找什么?你的问题不清楚
  • 你说你面临一个典型的场景,你没有说那个典型的场景是什么..请编辑你的问题以使其更有意义。
  • @PankajKumar,完全同意。但他想要的是,如果没有名字或中间名,他喜欢通过创建另一个 json 对象来进一步获取这些值。

标签: java android json


【解决方案1】:

将您的响应 JSON 解析为 JSONObject,然后为“name”键获取另一个 JSONObject,如果它抛出 JSONException,那么您的对象可能是一个字符串,如果您可以为您的“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;
}

【讨论】:

    【解决方案2】:

    您可以使用optJSONObject(name) 方法要求根JSONObject 返回给定名称的JSONObject(如果它存在并且是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
    }
    

    【讨论】:

    • 完全不知道 opt 方法......更优雅。 +1
    【解决方案3】:

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

    在我的解决方案中,不会有任何 Exception 被触发直到 JSON 错误。我正在做的是跟随。

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

    只需通过这个 sn-p,您就会找到解决问题的方法。

    // 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
    

    【讨论】:

      【解决方案4】:

      我也遇到过这样的问题。我不想手动解析 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 响应可以使用同一个类进行解析。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-31
        • 2013-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多