1

I have got the following string as HTTPResponse. It is in JSON format.

  [
    {
       "From":"en",
       "OriginalTextSentenceLengths":[
          5
       ],
       "TranslatedText":"Hallo",
       "TranslatedTextSentenceLengths":[
          5
       ]
    },
    {
       "From":"en",
       "OriginalTextSentenceLengths":[
          8
       ],
       "TranslatedText":"Frage",
       "TranslatedTextSentenceLengths":[
          5
       ]
   },
   {
       "From":"en",
       "OriginalTextSentenceLengths":[
          6
       ],
       "TranslatedText":"Antwort",
       "TranslatedTextSentenceLengths":[
          7
       ]
  }
]

So this string I am parsing as follows to get the "Translated Texts array"

  String resp = "[{\"From\":\"en\",\"OriginalTextSentenceLengths\":[5],\"TranslatedText\":\"Hallo\",\"TranslatedTextSentenceLengths\":[5]},{\"From\":\"en\",\"OriginalTextSentenceLengths\":[8],\"TranslatedText\":\"Frage\",\"TranslatedTextSentenceLengths\":[5]},{\"From\":\"en\",\"OriginalTextSentenceLengths\":[6],\"TranslatedText\":\"Antwort\",\"TranslatedTextSentenceLengths\":[7]}]";

    String[] stringArray = null;
    try {
    JSONArray finalResult=null;
    JSONTokener tokener = new JSONTokener(resp); 

        finalResult = new JSONArray(tokener);
        stringArray = new String[finalResult.length()];

    for(int i=0;i<finalResult.length();i++){
        JSONObject e = finalResult.getJSONObject(i);
        Log.v("TAG",e.getString("TranslatedText"));
        stringArray[i]=e.getString("TranslatedText");
    }        

    }catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 

I am getting the extracted "translated text" array ( Hallo, Frage, Antwort) out of the JSON Object...

But when I am doing the same procedure by giving the same string as input to JSONTokener directly i.e after getting HttpResponse as below, I am getting JSON Exception at finalResult = new JSONArray(tokener) line....

org.json.JSONException: End of input at character 0 of

String resp = getHttpResponse(uri);
String[] stringArray = null;
    try {
    JSONArray finalResult=null;
    JSONTokener tokener = new JSONTokener(resp); 

        finalResult = new JSONArray(tokener);
        stringArray = new String[finalResult.length()];

    for(int i=0;i<finalResult.length();i++){
        JSONObject e = finalResult.getJSONObject(i);
        Log.v("TAG",e.getString("TranslatedText"));
        stringArray[i]=e.getString("TranslatedText");
    }

    }catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 

I have tried hard for 2 days to resolve this error but couldn't do it.. So I am posting it here... Please help

EDIT:

I am adding the implementation of getHttpResponse

 public static String getHttpResponse(URI uri) {
    Log.d("APP_TAG", "Going to make a get request");
    StringBuilder response = new StringBuilder();
    try {
        HttpGet get = new HttpGet();
        get.setURI(uri);
        //DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpParams httpParameters = new BasicHttpParams(); 
        int timeoutConnection = 30000; 
        HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection); 
        int timeoutSocket = 30000; 
        HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket); 

        DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters); 

        Log.v("TAG","1");
        HttpResponse httpResponse = httpClient.execute(get);
        Log.v("TAG","2");
        if (httpResponse.getStatusLine().getStatusCode() == 200) {
            Log.d("demo", "HTTP Get succeeded");

            HttpEntity messageEntity = httpResponse.getEntity();
            InputStream is = messageEntity.getContent();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String line;
            while ((line = br.readLine()) != null) {
                response.append(line);
            }
        }
    } catch (Exception e) {
        Log.e("demo", e.getMessage());
    }
    Log.d("demo", "Done with HTTP getting");
    return response.toString();
}

And the uri which I am giving to getHttpResponse is as follows

   String[] texts = {"hello","question","answer"};
   final String params = "appId=" +   URLEncoder.encode("78280AF4DFA1CE1676AFE86340C690023A5AC139","UTF-8")                 
            + "&from=" + URLEncoder.encode("en","UTF-8")                 
            + "&to=" + URLEncoder.encode("de","UTF-8")                 
            + "&texts=" +   URLEncoder.encode(buildStringArrayParam(texts),"UTF-8");                

     final URL url = new  URL("http://api.microsofttranslator.com/V2/Ajax.svc/TranslateArray?" + params);       

     URI myURI = java.net.URI.create(url.toString()); 
     String resp = getHttpResponse(myURI);

This response string is what I am trying to parse...

This is for buildStringArrayParam(texts)

StringBuilder targetString = new StringBuilder("[\""); 
    String value;
    for(Object obj : values) {
        if(obj!=null) {
            value = obj.toString();
            if(value.length()!=0) {
                if(targetString.length()>2)
                    targetString.append(",\"");
                targetString.append(value);
                targetString.append("\"");
            }
        }
    }
    targetString.append("]");
    return targetString.toString();
DSP
  • 487
  • 2
  • 5
  • 18
  • If you log the `resp` string from `getHttpResponse()`, does it actually contain the JSON string you expect? – Philipp Reichart Apr 17 '12 at 10:32
  • Yes it contains the JSON string I expect... – DSP Apr 17 '12 at 10:37
  • Did you check that with `equals()`, comparing it your `String resp = "[{\"From\":\"...` constant? Could you add the `resp` you get from `getHttpResponse()` to you question? – Philipp Reichart Apr 17 '12 at 12:02
  • Also, it might help to see your implementaton of `getHttpResponse()`. – Philipp Reichart Apr 17 '12 at 12:06
  • Added implementation of 'getHttpResponse()' function... – DSP Apr 17 '12 at 12:33
  • You're currently ignoring any character encoding sent by the server. Try to use `String response = EntityUtils.toString(messageEntity);` instead of rolling your own with `InputStreamReader`. It's much less code and much more robust. – Philipp Reichart Apr 17 '12 at 13:15
  • Also, you might want to use [`BasicHttpParams`](http://developer.android.com/reference/org/apache/http/params/BasicHttpParams.html) and pass that to `HttpGet.setParams()` -- this will take care of all the URL encoding/escaping, so you don't have to. Don't add it all to the URL and encode it yourself. – Philipp Reichart Apr 17 '12 at 13:17
  • I used 'EntityUtils.toString(messageEntity);' but even then I am getting the same error...!! – DSP Apr 18 '12 at 05:10
  • What's the exact value of myUri right before you pass it to getHttpResponse()? Does that URL return what you expect when you open it in a browser? – Philipp Reichart Apr 18 '12 at 06:35
  • displaying myURI.toString() in logcat gave this output http://api.microsofttranslator.com/V2/Ajax.svc/TranslateArray?appId=78280AF4DFA1CE1676AFE86340C690023A5AC139&from=en&to=de&texts=%5B%22hello%22%2C%22question%22%2C%22answer%22%5D – DSP Apr 18 '12 at 06:41
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/10209/discussion-between-dsp-and-philipp-reichart) @phillip discussion was automatically moved to chat.. – DSP Apr 18 '12 at 06:42
  • The URL returned exactly what I expected when I opened it in a browser. – DSP Apr 18 '12 at 09:50
  • 1
    Check out my answer, I think I found the... crazy reason. – Philipp Reichart Apr 18 '12 at 11:51

4 Answers4

3

Ahaha... Microsoft.

At least in this case, they serve their API responses with an (incorrect?) FEFF FEFF UTF-16 byte order mark at the beginning which breaks most clients.

Like the PHP guys over here already found out, you just have to strip the first two bytes from the response. For exmaple in your code:

JSONTokener tokener = new JSONTokener(resp.substring(2));

I'm afraid the more harmless trim() doesn't work.

It's really hard to find, because FEFF's official name is "zero width no-break space" so it's completely invisible unless you look at your string as char array or notice how your text cursor stops when you move through a string using left/right arrow keys...

Note that you should not do this with any other HTTP response you receive, this is just for this Microsoft API (maybe others, too).

Community
  • 1
  • 1
Philipp Reichart
  • 20,771
  • 6
  • 58
  • 65
  • Hi, got a new exception now....org.json.JSONException: Value {"TranslatedText":"Hallo","TranslatedTextSentenceLengths":[5],"OriginalTextSentenceLengths":[5],"From":"en"} of type org.json.JSONObject cannot be converted to JSONArray – DSP Apr 18 '12 at 13:08
  • This occured at JSONTokener tokener = new JSONTokener(resp.substring(2)); line... – DSP Apr 18 '12 at 13:18
  • 1
    Try with `substring(1)` instead. I'm not sure if it worked with 2 for me because of the API returning a different BOM sometimes or my test case being wrong. – Philipp Reichart Apr 18 '12 at 13:41
  • 1
    Worst case, the API returns different BOMs at will and you have to try with substring(1) and substring(2) and pick whatever JSON can understand. – Philipp Reichart Apr 18 '12 at 13:44
  • Hi Philipp, you are truly awesome....!!!!! I changed it to 1, and it worked... :) Thanks a lot for finding this crazy reason...!! :) – DSP Apr 19 '12 at 03:54
2

Try GSON

And try to change your code design, hope it will help you.

And retrieve content from url -

public static String getContent(String url) throws Exception {
    return(new Scanner(new URL(url).openConnection().getInputStream()).useDelimiter("/z").next());
}

Have fun...

Suvam Roy
  • 1,282
  • 2
  • 11
  • 21
  • I can use GSON but the main thing which is bugging me is that, when JSON parsing is working in the 1st part , why it is failing in the second part? – DSP Apr 17 '12 at 11:28
0

Try using this:

HttpPost request = new HttpPost(URL);
HttpResponse response = httpClient.execute(request);

HttpEntity httpEntity = response.getEntity();
InputStream content = httpEntity.getContent();

BufferedReader reader = new BufferedReader(new InputStreamReader(content,"iso-8859-1"),8);
String resp = reader.readLine();

Now "resp" will hold the string which can be parsed...

PrincessLeiha
  • 3,144
  • 4
  • 32
  • 53
  • Actually the problem is not with HttpResponse because I am getting the response string correctly and I displayed it in the logcat...I used that string in the first code which I posted and it worked... – DSP Apr 17 '12 at 10:07
  • your URL support POST/GET HTTP method? check that once again! – PrincessLeiha Apr 17 '12 at 10:10
  • It supports GET because I have already got the response which I posted in the beginning... – DSP Apr 17 '12 at 10:16
0
After getting the HTTP Response you have to do this thing, you cant use Httpresponse directly.

HttpResponse response= null;
response = http.execute(get);
HttpEntity entity = response.getEntity();
String xmlstring = EntityUtils.toString(entity);
message = xmlstring;
Reddy
  • 140
  • 1
  • 5