【问题标题】:JSONException on trying to get a value from Json to String尝试从 Json 到 String 获取值时出现 JSONException
【发布时间】:2019-01-19 17:18:59
【问题描述】:

我正在尝试通过下一个 API 链接从 Wikipedia 获取 2 个值:

https://en.wikipedia.org/w/api.php?action=query&generator=random&grnnamespace=0&prop=pageimages&format=json&pithumbsize=500&utf8

因为它是随机生成的,有时它不会返回我需要的值之一,但我稍后会解决这个问题,目前我在访问 Json 中需要的两个值时遇到问题,“标题”和“来源”

返回的Json是这样的:

 {"batchcomplete":"","continue":{"grncontinue":"0.360395277951|0.360395626487|10429617|0","continue":"grncontinue||"},"query":{"pages":{"38690716":{"pageid":38690716,"ns":0,"title":"Alaine Chartrand","thumbnail":{"source":"https://upload.wikimedia.org/wikipedia/commons/d/d4/Alaine_Chartrand.jpg","width":267,"height":400},"pageimage":"Alaine_Chartrand.jpg"}}}}

这是代码,有人能弄清楚为什么会出现 JSONException 吗?

    String API = "https://en.wikipedia.org/w/api.php?action=query&generator=random&grnnamespace=0&prop=pageimages&format=json&pithumbsize=500&utf8";

    //open connection with wikipedia.
    HttpURLConnection httpcon = (HttpURLConnection) new URL(API).openConnection();

    //read all the input from wikipedia.
    BufferedReader in = new BufferedReader(new InputStreamReader(httpcon.getInputStream()));
    String responseSB = in.lines().collect(Collectors.joining());
    in.close();
    JSONObject incomingJSON = new JSONObject(responseSB);

    //crashes here
    String mTitle = incomingJSON.getString("title");
    String mUrl = incomingJSON.getString("source");

【问题讨论】:

    标签: java json


    【解决方案1】:

    如果您注意到 JSON,它是随机生成的,但具有特定格式

    案例 1

    {
    "batchcomplete": "",
    "continue": {
        "grncontinue": "0.720220803439|0.720221273467|12887566|0",
        "continue": "grncontinue||"
    },
    "query": {
        "pages": {
            "4897672": {
                "pageid": 4897672,
                "ns": 0,
                "title": "New Hope, Sunnyvale, Texas"
            }
        }
      }
    }
    

    querypages一直存在,并且在页面中key总是随机生成的,所以它是Map<String, JSONObject>映射StringJSONObject作为值,那么你需要得到@ 987654327@ 来自地图值的值

    String API = "https://en.wikipedia.org/w/api.php?action=query&generator=random&grnnamespace=0&prop=pageimages&format=json&pithumbsize=500&utf8";
    
        //open connection with wikipedia.
        HttpURLConnection httpcon = (HttpURLConnection) new URL(API).openConnection();
    
        //read all the input from wikipedia.
        BufferedReader in = new BufferedReader(new InputStreamReader(httpcon.getInputStream()));
        String responseSB = in.lines().collect(Collectors.joining());
        in.close();
        JSONObject incomingJSON = new JSONObject(responseSB);
    
      Map<String,JSONObject> map =  (Map<String, JSONObject>) incomingJSON.getJSONObject("query").getJSONObject("pages");
    
      map.forEach((k,v)->System.out.println(" The key is : "+k+" the title is : "+v.getString("title")));
    

    案例2有来源

    {
    "batchcomplete": "",
    "continue": {
        "grncontinue": "0.165621850014|0.165622038679|37982311|0",
        "continue": "grncontinue||"
    },
    "query": {
        "pages": {
            "57529788": {
                "pageid": 57529788,
                "ns": 0,
                "title": "Model Store",
                "thumbnail": {
                    "source": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Australia_New_South_Wales_relief_location_map.png/500px-Australia_New_South_Wales_relief_location_map.png",
                    "width": 500,
                    "height": 443
                },
                "pageimage": "Australia_New_South_Wales_relief_location_map.png"
                }
            }
        }
    }
    

    所以source 可能不会出现在每个响应中,请使用 try catch 处理

    String API = "https://en.wikipedia.org/w/api.php?action=query&generator=random&grnnamespace=0&prop=pageimages&format=json&pithumbsize=500&utf8";
    
        //open connection with wikipedia.
        HttpURLConnection httpcon = (HttpURLConnection) new URL(API).openConnection();
    
        //read all the input from wikipedia.
        BufferedReader in = new BufferedReader(new InputStreamReader(httpcon.getInputStream()));
        String responseSB = in.lines().collect(Collectors.joining());
        in.close();
        JSONObject incomingJSON = new JSONObject(responseSB);
    
      Map<String,JSONObject> map =  (Map<String, JSONObject>) incomingJSON.getJSONObject("query").getJSONObject("pages");
    
      map.forEach((k,v)->{
          System.out.println(" The key is : "+k+" the title is : "+v.getString("title"));  
    
          //use try catch to get source because you will not get the same response every time
    
          String source = v.getJSONObject("thumbnail").getString("source");
      });
    
    
    }
    

    【讨论】:

    • 嗨,我收到错误“语言级别 7 不支持 lambda 表达式”,据我了解,由于 map.forEach 行,它会给出此错误。我不确定什么是 lambda 表达式。还有其他方法吗?
    • 您使用的是 jdk 7,lambda 表达式来自 jdk-8,所以只需使用 for 循环来迭代 map
    • 不,我想出了另一个解决方案,我已经在这里发布了。
    【解决方案2】:

    您不能直接从 JSON 响应中获取标题和来源,因为它必须包含多个内部对象。以下是阅读标题和来源的代码快照。

    // new code
    JSONObject incomingJSON = new JSONObject(responseSB);
    JSONObject innerObject = incomingJSON.getJsonObject("query").getJsonObject("pages").getJsonObject("38690716");
    String mTitle= innerObject.getString("title");
    String mUrl= innerObject.getJsonObject("thumbnail").getString("source");
    
    
    //crashes here
    String mTitle = incomingJSON.getString("title");
    String mUrl = incomingJSON.getString("source");
    

    【讨论】:

    • 但并不总是 38690716
    • 好的,尝试使用索引而不是对象名称。
    【解决方案3】:

    试试这个...

    JSONObject incomingJSON = new JSONObject(responseSB);
    
    JSONObject TitleObjects = incomingJSON.getJSONObject("query");
    JSONObject j_Objects_01 = TitleObjects.getJSONObject("pages");
    JSONObject j_Objects_02 = j_Objects_01.getJSONObject("38690716");
    
    String mTitle = j_Objects_02.getString("title");
    JSONObject j_Objects_03 = j_Objects_02.getJSONObject("thumbnail");
    String mUrl = j_Objects_03.getString("source");
    

    【讨论】:

    • 并不总是 38690716
    【解决方案4】:

    您应该知道页面 ID 会发生变化,并且缩略图是可选的。

          // new code
          JSONObject incomingJSON = new JSONObject(responseSB);
          JSONObject pages = incomingJSON.getJSONObject("query").getJSONObject("pages");
          Iterator<String> it = pages.keys();
    
          while(it.hasNext()) {
              JSONObject page = pages.getJSONObject(it.next());
              String mTitle= page.getString("title");
              if(page.keySet().contains("thumbnail")) {
                  String mUrl= page.getJSONObject("thumbnail").getString("source");
              }
          }
    

    【讨论】:

      【解决方案5】:

      因此,由于 ID 不断变化,我决定采用另一种方法。 我使用了以下代码:

          Pattern p = Pattern.compile("\"source\":\"(.*?)\",\"width");
          Matcher m = p.matcher(responseSB);
      
              if (m.find()) {
                  url = m.group(1);
              }
      
              p = Pattern.compile("\"title\":(.*?)\",\"thumbnail");
              m = p.matcher(responseSB);
      
              if (m.find()) {
                  description = m.group(1);
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-09
        • 2022-09-24
        • 2023-03-17
        • 2021-12-28
        • 2023-04-09
        相关资源
        最近更新 更多