JSON解析适用于Android 4.0但不适用于Android< 4

时间:2012-06-16 14:26:59

标签: android json parsing

  

可能重复:
  JSON parsing problem

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

<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上运行,但在旧设备上却无法运行。

here

中找到Json

12 个答案:

答案 0 :(得分:3)

在较新的Android版本中,JSONObject解析器可能更加宽松。您收到的错误消息似乎是由于可疑的合法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);
    }
  }
}

答案 1 :(得分:2)

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

  1. 打开连接并获得回复。
  2. 获取内容并创建字符串构建器。
  3. 将字符串构建器变为json数组对象(此步骤尚未完成)
  4. 从json数组对象中获取json对象。
  5. 我认为您错过了将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*/

答案 2 :(得分: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;
    }
}

希望它有所帮助。

答案 3 :(得分: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 !!");
}

我希望这会对你有所帮助。

答案 4 :(得分:2)

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

JSON parsing problem

答案 5 :(得分:1)

我不太清楚你为什么会收到这个错误。但我也遇到过类似的问题,它通过更改charSet来解决。尝试使用iso-8859-1代替UTF-8

答案 6 :(得分:1)

你试过杰克逊吗?我已经在每个版本的android上使用它,它的效果非常好。

http://jackson.codehaus.org/

答案 7 :(得分:1)

您是否尝试过JSONParser?

这是我使用的一个例子:

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


    try {

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

    } catch (ParseException e) {        
        e.printStackTrace();
    }

答案 8 :(得分:1)

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

我注意到的一些事情:

  • InputStream isString jsonJSONObject jObj在您的getJSONFromUrl()方法的外部声明,并且它们可能会因某种其他方式而受到不同的影响。与其他API相比,在一个API上运行时的代码。

  • 查看您获得的异常,由于String构造函数的输入JSONObject为空字符串(“”),可能会抛出它。是否有可能您的服务器为您的旧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 ----
    

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

答案 9 :(得分:1)

杰克逊或GSON。

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

我会重启Eclipse,做一个干净的构建并再试一次。

答案 10 :(得分:1)

行中json

中名为json = sb.toString();的变量的类型是什么

是字符串吗?如果是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;
    }
}

答案 11 :(得分:0)

当然这会奏效。在4.0 android版本中,我们必须创建asynctask以避免异常,即NetworkOnMainThreadException ll get。它对我来说很好。

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());
    }

}

}

享受..