5

可能重复:
JSON 解析问题

我正在解析一个 JSON 文件(这是有效的)。它适用于 Android 4.0 - 4.0.4,但不适用于较旧的 Android 版本。这是我的清单的一部分:

<uses-sdk
    android:minSdkVersion="7"
    android:targetSdkVersion="14" />

这是我的解析代码:

public JSONObject getJSONFromUrl(String url) {
    try {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        is = httpEntity.getContent();

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                is, "UTF-8"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        is.close();
        json = sb.toString();
    } catch (Exception e) {
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }

    try {
        jObj = new JSONObject(json);
    } catch (JSONException e) {
        Log.e("JSON Parser", "Error parsing data " + e.toString());
    }

    return jObj;

}

在旧设备上,我收到以下错误消息(但正如我所说,不是在新的 Android 设备上):

org.json.JSONException:java.lang.String 类型的值无法转换为 JSONObject

我完全不知道为什么它可以在 Android 4 上运行,但不能在旧设备上运行。

从这里找到 Json

4

12 回答 12

3

解析器可能JSONObject在较新的 Android 版本中变得更加宽松。您收到的错误消息似乎是由于可疑的合法 JSON 造成的,尤其是在接收方:

我建议您将下载的 JSON 写入文件并将其与原始文件进行比较,以查看下载逻辑是否存在问题。


更新

我无法重现您的问题。在 Android 4.0.3.、2.3.3、2.2 和 2.1 上,使用以下活动从外部存储中加载 JSON 工作得非常好(注意:我在外部存储的路径中很懒且硬连线):

package com.commonsware.jsontest;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import org.json.JSONException;
import org.json.JSONObject;

public class JSONTestActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    try {
      BufferedReader in=
          new BufferedReader(new FileReader("/mnt/sdcard/test.json"));
      String str;
      StringBuilder buf=new StringBuilder();

      while ((str=in.readLine()) != null) {
        buf.append(str);
        buf.append("\n");
      }

      in.close();
      JSONObject json=new JSONObject(buf.toString());

      ((TextView)findViewById(R.id.stuff)).setText(json.toString());
    }
    catch (IOException e) {
      Log.e(getClass().getSimpleName(), "Exception loading file", e);
    }
    catch (JSONException e) {
      Log.e(getClass().getSimpleName(), "Exception parsing file", e);
    }
  }
}
于 2012-06-18T15:27:54.863 回答
2

这里的解决方案将解决您的问题,这是因为从服务器返回的 utf-8 编码。

JSON解析问题

于 2012-10-08T04:10:53.337 回答
2

您好,我使用了以下代码,在 2.2 中没有出现任何错误,2.3.3 代码非常简单。

import java.io.IOException;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class NannuExpActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        try {
            JSONObject jo = getJSONObjectFromUrl("http://pastebin.com/raw.php?i=Jp6Z2wmX");
            for(int i=0;i<jo.getJSONArray("map_locations").length();i++)
            Log.d("Data",jo.getJSONArray("map_locations").getJSONObject(i).getString("title"));
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

    public JSONObject getJSONObjectFromUrl(String url) throws ClientProtocolException, IOException, JSONException{
        JSONObject jobj = null;
        HttpClient hc = new DefaultHttpClient();
        HttpGet hGet = new HttpGet(url);
        ResponseHandler<String> rHand = new BasicResponseHandler();
        String resp = "";
        resp = hc.execute(hGet,rHand);
        jobj = new JSONObject(resp);    
        return jobj;
    }
}

希望能帮助到你。

于 2012-06-21T17:13:48.793 回答
2

通常这些是通过android中的Http连接创建json对象的以下步骤。

  1. 打开连接并获得响应。
  2. 获取内容并创建一个字符串生成器。
  3. 将字符串生成器变成 json 数组对象(这一步你还没有做)
  4. 从 json 数组对象中获取 json 对象。

我认为您错过了将 String Buffer(sb) 转换为 json 数组对象。而不是直接从字符串缓冲区创建 json 对象。我不知道它在 android 4.0 中是如何工作的。修改后的代码是

public JSONObject getJSONFromUrl(String url) {
    try {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        is = httpEntity.getContent();

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                is, "UTF-8"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        is.close();
        json = sb.toString();
    } catch (Exception e) {
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }

    try {
       JSONArray jObj = new JSONArray(json);
    } catch (JSONException e) {
        Log.e("JSON Parser", "Error parsing data " + e.toString());
    }

    return jObj;

}

您可以通过传递索引值来获取 json 对象,例如,

jObj.getJSONObject(i); /*i is a integer, index value*/

于 2012-06-18T17:57:47.307 回答
2

我为 json 使用了以下代码,对我来说它支持所有 android 版本。

List<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("data", qry));
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters);

HttpPost request = new HttpPost(your url);
request.setEntity(formEntity);

HttpResponse rp = hc.execute(request);
Log.d("UkootLog", "Http status code " + rp.getStatusLine().getStatusCode());

if (rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK
    || rp.getStatusLine().getStatusCode() >= 600) {
  Log.d("JsonLog", "Success !!");
  String result = EntityUtils.toString(rp.getEntity());
} else {
  Log.d("UkootLog", "Failed while request json !!");
}

我希望这能帮到您。

于 2012-06-22T12:36:00.313 回答
1

你试过 JSONParser 吗?

这是我使用的一个例子:

   JSONObject json = new JSONObject();
   JSONParser jsonParser = new JSONParser(); 


    try {

        if(jsonString != null)
            json =  (JSONObject) jsonParser.parse(jsonString);

    } catch (ParseException e) {        
        e.printStackTrace();
    }
于 2012-06-19T15:45:53.263 回答
1

你试过杰克逊吗?我在每个版本的 android 上都使用过它,而且效果很好。

http://jackson.codehaus.org/

于 2012-06-19T15:41:09.790 回答
1

该行中调用的变量的类型是什么jsonjson = sb.toString();

它是一个字符串吗?如果它是 a JSONObject,将其类型更改为String,您的代码将完美运行。


另一个注意事项是异常处理:似乎如果在构建 String 时在第一个块中引发异常,JSONObject则将尝试使用一些错误数据进行初始化。


无论如何试试这个(我怀疑你的下载方法有问题):

public JSONObject getJSONFromUrl(String url) {
    try {
        HttpPost postMethod = new HttpPost(SERVER_URL);
        ResponseHandler<String> res = new BasicResponseHandler();
        ResponseHandler<String> res = new ResponseHandler<String>() {
            public String handleResponse(final HttpResponse response) throws HttpResponseException, IOException {
                StatusLine statusLine = response.getStatusLine();
                if (statusLine.getStatusCode() >= 300) {
                    throw new HttpResponseException(
                    statusLine.getStatusCode(),
                    statusLine.getReasonPhrase());
                }
                HttpEntity entity = response.getEntity();
                return entity == null ? null : EntityUtils.toString(entity, "UTF-8");
            }
        };

        String response = (new DefaultHttpClient()).execute(postMethod, res);
        return new JSONObject(json);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
于 2012-06-25T09:23:11.087 回答
1

杰克逊或 GSON。

可能是那里的德语额外字符和国际化(i18n)或utf-8问题。

我会重新启动 Eclipse,做一个干净的构建,然后再试一次。

于 2012-06-22T02:41:54.940 回答
1

我复制了您的代码并使用http://pastebin.com/raw.php?i=Jp6Z2wmX作为您getJSONFromUrl(String url)方法的输入。有趣的是,我无法重现您的问题(使用 AVD 和/或 15、10 或 7 的目标 API 的几种组合)。

我确实注意到了一些事情:

  • InputStream is, String json,JSONObject jObj是在您的方法外部声明的getJSONFromUrl(),并且当在一个 API 上运行时,与另一个 API 相比,它们可能会受到代码其他部分的不同影响。

  • 查看您得到的异常,很可能是由于构造函数的输入是空字符串(“”)而引发StringJSONObject。您的服务器是否有可能以某种方式为您的旧 Android 提供了不同的数据?

以下是我的建议:

  • 将以下行添加到getJSONFromUrl()方法的顶部:

    InputStream is = null;
    String json = null;
    JSONObject jObj = null;
    
  • 添加一行调试代码以在最后 2 个 try-catch 块之间打印出下载的字符串,如下所示:

    // ----- cut ----
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }
    
    Log.d("getJSONFromUrl", "json=(" + json + ")");
    
    try {
        jObj = new JSONObject(json);
    // ----- cut ----
    

我认为在您进行上述一项或两项更改后,我们会更多地了解您的问题 :)

于 2012-06-19T21:48:25.340 回答
1

我不太确定您为什么会收到此错误。但我也遇到过类似的问题,通过更改 charSet 解决了。尝试使用iso-8859-1而不是UTF-8.

于 2012-06-19T08:03:43.887 回答
0

这肯定会奏效。在 4.0 android 版本中,我们必须创建 asynctask 以避免异常,即NetworkOnMainThreadException会得到。它对我来说工作正常。

public class Http_Get_JsonActivity extends Activity implements OnClickListener {


String d = new Date().toString();

private static final String TAG = "MyPost";

private boolean post_is_running = false;

private doSomethingDelayed doSth;

private String url = "http://192.168.1.1";
private InputStream is;
private String json;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);



    Button pushButton = (Button) findViewById(R.id.button1);
    pushButton.setOnClickListener(this);

}

@Override
protected void onPause() {
    super.onPause();
    if (post_is_running) { // stop async task if it's running if app gets
                            // paused
        Log.v(TAG, "Stopping Async Task onPause");
        doSth.cancel(true);
    }
}

@Override
protected void onResume() {
    super.onResume();
    if (post_is_running) {
        // start async task if it was running previously and was stopped by
        // onPause()
        Log.v(TAG, "Starting Async Task onResume");
        doSth = (doSomethingDelayed) new doSomethingDelayed().execute();
        // ((Button) findViewById(R.id.push_button)).setText("Resuming..");
    }
}

public void onClick(View v) {

    if (post_is_running == false) {
        post_is_running = true;
        Log.v(TAG, "Starting Async Task onClick");
        doSth = (doSomethingDelayed) new doSomethingDelayed().execute();

        // ((Button) findViewById(R.id.push_button)).setText("Starting..");
    } else {
        Log.v(TAG, "Stopping Async Task onClick");
        post_is_running = false;
        doSth.cancel(true);
        // ((Button) findViewById(R.id.push_button)).setText("Stopping..");
    }
}

private class doSomethingDelayed extends AsyncTask<Void, Integer, Void> {

    private int num_runs = 0;

    @Override
    protected Void doInBackground(Void... gurk) {

        // while (!this.isCancelled()) {
        Log.v(TAG, "going into postData");

        long ms_before = SystemClock.uptimeMillis();
        Log.v(TAG, "Time Now is " + ms_before);

        postData();

        Log.v(TAG, "coming out of postData");

        publishProgress(num_runs);

        return null;
    }

    @Override
    protected void onCancelled() {
        Context context = getApplicationContext();
        CharSequence text = "Cancelled BG-Thread";
        int duration = Toast.LENGTH_LONG;

        Toast.makeText(context, text, duration).show();

    }

    @Override
    protected void onProgressUpdate(Integer... num_runs) {
        Context context = getApplicationContext();
    }
}

/**
 * Method to send data to the server
 */

public void postData() {
    try {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet httpPost = new HttpGet(url);
        System.out.println("--httppost----" + httpPost);
        HttpResponse httpResponse = httpClient.execute(httpPost);
        System.out.println("--httpResponse----" + httpResponse);
        HttpEntity httpEntity = httpResponse.getEntity();
        System.out.println("--httpEntity----" + httpEntity);
        is = httpEntity.getContent();
        System.out.println("--is----" + is);

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                is, "UTF-8"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        is.close();
        json = sb.toString();
    } catch (Exception e) {
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }

    try {
        JSONArray jObj = new JSONArray(json);
        System.out.println("--jObjt--" + jObj);
    } catch (JSONException e) {
        Log.e("JSON Parser", "Error parsing data " + e.toString());
    }

}

}

请享用..

于 2012-06-22T12:08:52.370 回答