2012-06-16 63 views
5

可能重复:
JSON parsing problemJSON解析适用于Android 4.0,但不是在Android <4.0

我解析一个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上工作,但不能在较旧的设备上工作。

here

+0

粘贴整个json在这里!或者尝试在www.jsonlint.com.tw上进行验证。我怀疑json有一些问题。 –

+0

正如我所说(我现在再次验证与jsonlint.com)这是一个有效的JSON ...而奇怪的是,它适用于Android 4 ... – user754730

+0

你确定org.json库的版本是两台设备上都一样?此外,增加缓冲读取器的缓冲区大小。 – wdziemia

回答

3

找到的Json这是可能的JSONObject解析器已取得新型Android版本较为宽松。您收到此错误信息出现是由于半信半疑法律JSON,特别是在接收端:

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


UPDATE

我无法重现你的问题。使用以下活动(注意:我在通往外部存储器的路径中是懒惰且硬连线的),在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); 
    } 
    } 
} 
+0

尝试过,但它给出了与我在服务器上相同的EXACT文件。 – user754730

+0

@ user754730:在这一点上,除非你能给我们一个重现错误的项目,否则我怀疑任何人都可以真正帮助你。 – CommonsWare

+0

那么你需要更多的代码? – user754730

2

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

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

我想你错过了将字符串缓冲区(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*/

+0

非常感谢这种方法!不幸的是,这不工作在2.1/2.2不在4.0 :( – user754730

1

我不是很清楚为什么你得到这个错误。但我也遇到了类似的问题,并通过更改charSet来解决。尝试使用iso-8859-1而不是UTF-8

+0

这实际上是我以前做过的。这不适用于任何版本:( – user754730

1

您是否尝试过的JSONParser?

这里是一个例子至极我使用:

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


    try { 

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

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

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

有些事情我也注意到:

  • InputStream isString jsonJSONObject jObj声明外部到您的getJSONFromUrl()方法,有一种可能性,即它们是由你的代码的其他部分上运行时,不知何故影响不同一个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 ---- 
    

我想我们会知道更多关于你的问题,你做出的上述变化的一方或双方:)后

+0

非常感谢您的帮助! 我已经有这3行在我的代码之前... 然后我试着记录的东西,它只是打印出我的完整的JSON,然后像以前一样抛出异常: – user754730

+1

有趣的,你可以尝试调用你的'getJSONFromUrl(url)'方法传递'http: // pastebin.com/Jp6Z2wmX'和'http://pastebin.com/raw.php?i=Jp6Z2wmX'作为'url'的值?如果你能够看到这两个logcat的输出,我会非常好奇的它也在pastebin上 – Joe

+0

哇奇怪的是,它完全适用于2.2和4.0,我不知道为什么? 所以目前情况如此:我们的服务器=不工作, Android 4 + Pastebin = WORKS, Android <4 + Pastebin =工作 – user754730

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

希望它有帮助。

1

Jackson或GSON。

可能是德国的额外字符,还有国际化(i18n)或utf-8问题。

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

+1

这是否已经....也许逃避多余的字符可以帮助?! – user754730

+0

转义是一个好主意或uuencoding/mime编码/ url编码 –

+0

试过了...没有帮助: – user754730

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

} 

} 

享受..

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 !!"); 
} 

我希望这会帮助你。

1

什么是变量的类型称为行jsonjson = sb.toString();

是一个字符串?如果它是JSONObject,请将其类型更改为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; 
    } 
} 
+0

不幸的是,这不适用于Android 2.2 ...虽然它在Android 4上工作,但... – user754730

相关问题