【问题标题】:Parsing JSONArray with Double in Android Studio在 Android Studio 中使用 Double 解析 JSONArray
【发布时间】:2016-09-06 10:11:28
【问题描述】:

我正在尝试从 Android Studio 中的 MySQL 数据库解析 JSONArray,但出现以下异常:

org.json.JSONException: Value {"success":false,"0":{"success":false,"marker_id":null,"lat":null,"lng":null,"snippet":null},"1":{"success":false,"marker_id":null,"lat":null,"lng":null,"snippet":null},"2":{"success":false,"marker_id":null,"lat":null,"lng":null,"snippet":null},"3":{"success":false,"marker_id":null,"lat":null,"lng":null,"snippet":null}} of type org.json.JSONObject cannot be converted to JSONArray

我要做的是解析几个包含双精度值的标记 LatLng,然后将这些标记放在谷歌地图中。

放置标记和发出请求的代码:

Response.Listener<String> responseListener = new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        try {

                            JSONArray jsonResponse = new JSONArray(response);
                            Log.i("RESPONSE:", "[" + jsonResponse + "]");


                            for (int i = 0; i < response.length(); i++) {

                                //boolean success = jsonResponse.getBoolean("success");
                                //double lat = jsonResponse.getDouble("lat");
                                //double lng = jsonResponse.getDouble("lng");
                                //int snippet = jsonResponse.getInt("snippet");



                                //LatLng Mplace = new LatLng(lat, lng);

                                //MarkerOptions marker = new MarkerOptions().position(Mplace).title("Marker").snippet("Snippet:" + "0");
                                //mMap.addMarker(marker);


                            }


                        } catch (JSONException e) {
                            e.printStackTrace();
                            Log.i("RESPONSE:", "[" + response + "]");
                            Toast.makeText(getApplicationContext(),
                                    "Error: " + e.getMessage(),
                                    Toast.LENGTH_LONG).show();
                        }

                    }

                };

                MarkerRequest markerRequest = new MarkerRequest(responseListener);
                RequestQueue queue = Volley.newRequestQueue(AllMarkersActivity.this);
                queue.add(markerRequest);

现在我已经评论了标记的实际放置,这就是我得到上面显示的异常的时候。当我删除评论时,我会收到这条红色短信:

getDouble (int) cannot be applied to (java.lang.String)

这是我的请求代码:

public class MarkerRequest extends StringRequest {
private static final String MARKER_REQUEST_URL = "http://simonjensen.comxa.com/GetMarkers.php";
private Map<String, String> params;
//private JSONObject data = new JSONObject("http://simonjensen.comxa.com/GetMarkers.php");

public MarkerRequest(Response.Listener<String> listener){
    super(Request.Method.POST, MARKER_REQUEST_URL, listener, null);
    params = new HashMap<>();
}
@Override
public Map<String, String> getParams() {
    return params;
}

这是我的 PHP 脚本:

<?php
$con = mysqli_connect("myhost", "myuser", "mypass", "mydatabase");

/*$statement = mysqli_prepare($con);

$sql = "SELECT * FROM markers   ORDER BY marker_id  ASC ";
$strSQL = "SELECT * FROM `markers`  ORDER BY marker_id  ASC ";

$objQuery = mysql_query($statement, $strSQL) or die(mysql_error());
$arrRows = array();
$arryItem = array();*/

$statement = mysqli_prepare($con, "SELECT * FROM markers    ORDER BY marker_id  ASC ");
    mysqli_stmt_execute($statement);
//mysqli_stmt_bind_result($statement, $colmarker_id, $collat, $collng, $colsnippet);

//$response = array();
$arrRows = array();
$arryItem = array();
    //$response["success"] = false;
$arrRows["success"] = false;
$arryItem["success"] = false;

while(mysqli_stmt_fetch($statement)) {
    $arryItem["marker_id"] = $arr["marker_id"];
    $arryItem["lat"] = $arr["lat"];
    $arryItem["lng"] = $arr["lng"];
    $arryItem["snippet"] = $arr["snippet"];
    $arrRows[] = $arryItem;
}

echo json_encode($arrRows);
?>

所以我的问题可以缩小到这个:

如何解析JSONArray(在数组中?),以及如何解析JSONArray 中的双精度值?

有一个代码示例会很好,因为我还在学习:)

谢谢!

【问题讨论】:

  • 您的 json 不包含数组,它在单个对象中包含对象。数组由“[”表示。

标签: php android mysql arrays json


【解决方案1】:

由于您的响应包含 JSON 对象,而外部 JSON 对象包含内部 JSON 对象。因此,首先将其解析为 JSON 对象,然后获取 Lat 和 lng。试试这个代码:

    JSONObject jsonObject = new JSONObject(response);
    Iterator<String> keys = jsonObject.keys();
    while( keys.hasNext() )
    {
        String key = keys.next();
                if(!key.equals("success")){   // or use this if your keys are always in digits form.. if(TextUtils.isDigitsOnly(key))
                    Log.v("category key", key);
                    JSONObject innerJObject = jsonObject.getJSONObject(key);
                    String lat_str = innerJObject.getString("lat");
                    double lat = 0.0, lng = 0.0;

                    if(!TextUtils.isEmpty(lat_str) &&      TextUtils.isDigitsOnly(lat_str))
                        lat = Double.parseDouble(lat_str);

                    String lng_str = innerJObject.getString("lng");

                    if(!TextUtils.isEmpty(lng_str) && TextUtils.isDigitsOnly(lng_str))
                        lng = Double.parseDouble(lng_str);

                }
    }

在此块中添加异常处理。这可能会有所帮助!

【讨论】:

  • 我试过这个并得到了异常:org.json.JSONException: Value false at success of type java.lang.Boolean cannot be convert to JSONObject
  • 我已经编辑了我的答案,现在检查。这是因为我们拥有“成功”不是关键,而是布尔值。所以,现在检查并告诉我:)
  • 如果您认为您的密钥始终是数字形式,您也可以使用此 TextUtils.isDigitsOnly(key) 而不是 !key.equals("success")。
  • 好的,我这样做了,我认为这行得通!谢谢!我将此答案标记为已接受,因为我相当确定这可以解决问题。我收到一份编舞日志,上面写着:“我/编舞:跳过了 33 帧!应用程序可能在其主线程上做了太多工作。”这告诉我它可能加载太多(这意味着我猜它必须工作)。现在只需要弄清楚如何在后台线程中执行此操作 :) 谢谢!
  • 欢迎兄弟!!欣赏后感到幸福。并在您的 JSON 响应中正确地测试添加一些正确的日期,然后您就会明白这一点。 :)
【解决方案2】:

似乎您正在传递字符串数据而不是双精度值。尝试这样做:

 String lat_str = jsonResponse.getString("lat");
 double lat = Double.parseDouble(lat_str);
 String lng_str = jsonResponse.getString("lng");
 double lng = Double.parseDouble(lng_str);

【讨论】:

  • 我试过用 JSONArray 和 JSONObject 做这件事,用数组它给我和 double 一样的红色文本,就像这样:getString (int) cannot be applied to (java.lang.String ) 和 JSONObject 它给了我: org.json.JSONException: No value for lat
【解决方案3】:
try {

                JSONArray jsonResponse = new JSONArray(response);
                Log.i("RESPONSE:", "[" + jsonResponse + "]");
                for (int i = 0; i < jsonResponse.length(); i++) {
                    JSONObject obj = jsonResponse.getJSONObject(i);



                    boolean success = obj.getBoolean("success");
                    double lat = obj.getDouble("lat");
                    double lng = obj.getDouble("lng");
                    int snippet = obj.getInt("snippet");


                    LatLng Mplace = new LatLng(lat, lng);
                    MarkerOptions marker = new MarkerOptions().position(Mplace).title("Marker").snippet("Snippet:" + "0");
                    mMap.addMarker(marker);


                }


            } catch (JSONException e) {
                e.printStackTrace();
                Log.i("RESPONSE:", "[" + response + "]");
                Toast.makeText(getApplicationContext(),
                        "Error: " + e.getMessage(),
                        Toast.LENGTH_LONG).show();
            }

【讨论】:

  • 这似乎消除了红色文本错误,但我仍然得到 JSON 异常: org.json.JSONException: Value {"success":false,"0":{"success":false ,"marker_id":null,"lat":null,"lng":null,"sn-p":null},"1":{"success":false,"marker_id":null,"lat":null ,"lng":null,"sn-p":null},"2":{"success":false,"marker_id":null,"lat":null,"lng":null,"sn-p" :null},"3":{"success":false,"marker_id":null,"lat":null,"lng":null,"sn-p":null}} 类型 org.json.JSONObject 不能转换为 JSONArray
  • 响应=“[”+响应+“]”;在 JSONArray jsonResponse = new JSONArray(response); 之前添加这一行并在循环更新起点 for (int i = 1; i
  • 就像其他两个答案一样,我很确定这也有效,因为我收到了一个编舞日志,上面写着:“我/编舞:跳过 33 帧!应用程序可能做的工作太多在它的主线程上。”这告诉我它可能加载太多(这意味着我猜它必须工作)。现在只需要弄清楚如何在后台线程中执行此操作:) 谢谢!
【解决方案4】:

改变这个

 JSONArray jsonResponse = new JSONArray(response);

 JSONObject jsonResponse = new JSONObject(response);

获取纬度值使用以下。

 double lat = jsonResponse.getJSONObject("0").optDouble("lat");

【讨论】:

  • 我已经尝试过这样做,但后来我得到:org.json.JSONException: No value for lat - 这让我觉得我必须做 aprse JSONArray
  • 谢谢! ''sorta'' 使它工作,它现在没有给我任何例外,但我仍然在我的 JSONresponse 中得到空值。是什么赋予了?响应是这样的,并将标记放在 gmaps 的中间: I/RESPONSE: {"success":false,"0":{"success":false,"marker_id":null,"lat":null, "lng":null,"sn-p":null},"1":{"success":false,"marker_id":null,"lat":null,"lng":null,"sn-p": null},"2":{"success":false,"marker_id":null,"lat":null,"lng":null,"sn-p":null},"3":{"success": false,"marker_id":null,"lat":null,"lng":null,"sn-p":null}}
  • 你得到了什么空值?
  • @SimonA.CallaghanJensen 如果答案正确,您应该先接受答案。
  • 很好,这样做消除了 JSON 异常,但我仍然没有正确解析数据。就像我之前的评论一样,我正在解析空值。数据库不包含空值,因此这些值仍然必须以某种方式解析错误。我不知道是不是我的php错了,但是问题仍然没有答案,但更接近答案:)答案仍然有用!
【解决方案5】:
 Response.Listener<String> responseListener = new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    try {

        JSONObject jsonResponse = new JSONObject(json);


        boolean flag = true;
        int i = 0;
        while (flag) {

            try {
                JSONObject jsonInnerObject = new      JSONObject(jsonResponse.get(String.valueOf(i)).toString());
                Object success = jsonInnerObject.get("success");
                Object marker_id = jsonInnerObject.get("marker_id");
                Object lat = jsonInnerObject.get("lat");
                Object lng = jsonInnerObject.get("lng");
                Object snippet = jsonInnerObject.get("snippet");
                i++;
            } catch (Exception e) {
                flag = false;
            }


        }



                        } catch (JSONException e) {
                        e.printStackTrace();
                        Log.i("RESPONSE:", "[" + response + "]");
                        Toast.makeText(getApplicationContext(),
                                "Error: " + e.getMessage(),
                                Toast.LENGTH_LONG).show();
                    }

【讨论】:

  • 当我这样做时,我没有得到任何登录 logcat 的响应。但是,它没有给我任何例外。我将如何使用这种方法放置标记?谢谢!
  • @SimonA.CallaghanJensen 我没有对响应做任何事情,这就是它不显示的原因可以在这里用值做任何你想做的事情
  • 我这样做了,就像其他答案一样,我得到了一个编舞日志,上面写着:“我/编舞:跳过了 33 帧!应用程序可能在其主线程上做了太多工作。”这告诉我它可能加载太多(这意味着我猜它必须工作)。现在只需要弄清楚如何在后台线程中执行此操作:) 谢谢!
  • 您可以为此目的使用aysncTask()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-12
  • 1970-01-01
相关资源
最近更新 更多