2014-06-05 11 views
9

fino ad ora ho usato il seguente frammento di codice al fine di inviare e ricevere stringhe JSON:Invio UTF-8 stringa utilizzando HttpURLConnection

static private String sendJson(String json,String url){ 
    HttpClient httpClient = new DefaultHttpClient(); 
    String responseString = ""; 
    try { 
     HttpPost request = new HttpPost(url); 
     StringEntity params =new StringEntity(json, "UTF-8"); 
     request.addHeader("content-type", "application/json"); 
     request.setEntity(params); 
     HttpResponse response = httpClient.execute(request); 
     HttpEntity entity = response.getEntity(); 
     responseString = EntityUtils.toString(entity, "UTF-8"); 

    }catch (Exception ex) { 
     ex.printStackTrace(); 
     // handle exception here 
    } finally { 
     httpClient.getConnectionManager().shutdown(); 
    } 
    return responseString; 
} 

Il codice di cui sopra ha funzionato perfettamente, anche se la stringa JSON contenuta UTF-8 chars, e tutto ha funzionato bene.

Per diverse ragioni, ho dovuto modificare il modo in cui invio richieste HTTP e utilizzare HttpURLConnection invece HttpClient di apache. Qui è il mio codice:

static private String sendJson(String json,String url){ 
    String responseString = ""; 
    try { 
     URL m_url = new URL(url); 
     HttpURLConnection conn = (HttpURLConnection)m_url.openConnection(); 
     conn.setDoInput(true); 
     conn.setDoOutput(true); 
     conn.setUseCaches(false); 
     conn.setRequestMethod("POST"); 
     conn.setRequestProperty("content-type", "application/json"); 
     DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream()); 
     outputStream.writeBytes(json); 
     outputStream.flush(); 
     outputStream.close(); 

     BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
     StringBuilder sb = new StringBuilder(); 
     String line; 
     while ((line = br.readLine()) != null) { 
      sb.append(line+"\n"); 
     } 
     br.close(); 
     responseString = sb.toString(); 
    } catch (MalformedURLException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    return responseString; 
} 

Questo codice funziona bene per le normali caratteri inglesi, ma non sembra supportare i caratteri UTF-8 nella stringa JSON, poiché non ogni volta. (quando si invia json al server, il server si schiaccia dicendo che utf8 non può decodificare un certo byte, ma quando ricevo utf8 json dal server, penso che funzioni, dal momento che riesco a visualizzare i caratteri speciali).

Il server non è stato modificato e ha funzionato correttamente con il codice precedente, quindi il problema è al 100% su questo nuovo frammento di codice.

Qualche idea su come correggere l'invio della stringa json in modo da supportare UTF 8? Grazie

risposta

22

Penso che il problema è in questa parte:

DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream()); 
outputStream.writeBytes(json); 
outputStream.flush(); 
outputStream.close(); 

Invece di fare questo è necessario codificare JSON come UTF-8
e inviare tali byte che rappresentano la codifica UTF-8.

Prova ad usare questo:

Charset.forName("UTF-8").encode(json) 

See:

Charset.encode

Un approccio ancora più semplice è quello di utilizzare per esempio a BufferedWriter a capo di uno
OutputStreamWriter. Il OutputStreamWriter conosce la propria codifica
e quindi farà il lavoro per voi (il lavoro di codifica della stringa json).

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8")); 
bw.write(json); 
bw.flush(); 
bw.close(); 
+2

Perfetto. Grazie e buona giornata. – Jjang

1

Quando si scrive una String ad un flusso di output (byte), è necessario specificare la codifica per eseguire la conversione. Un modo per fare è avvolgere il flusso di output in un OutputStreamWriter che utilizzerà il set di caratteri UTF-8 per la codifica.

 conn.setRequestProperty("content-type", "application/json; charset=utf-8"); 
     Writer writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8")); 
     writer.write(json); 
     writer.close(); 

Il flush() è anche facoltativa se si chiama close().

Un'altra opzione, come menzionata da peter.petrov consiste nel convertire prima il tuo String in byte (in memoria) e quindi inviare l'array di byte al flusso di output.

E per rendere evidente sul lato server, è possibile passare il set di caratteri utilizzato nell'intestazione del tipo di contenuto ("content-type", "application/json; charset=utf-8").

1

StringEntity utilizza uno Charset per assicurarsi che la codifica sia corretta.Lo fa ~ che:

byte[] content = s.getBytes(charset); 

senza cambiare molto nel codice, il vostro articolo può essere:

outputStream.write(json.getBytes("UTF-8")); 

Per quanto riguarda la tua lettura, non v'è alcun punto nel usando un BufferedReader con readLine, ad eccezione di normalizzazione la fine della linea. È molto più lento di altri metodi, poiché richiede di leggere ogni byte individualmente.

EntityUtils fa principalmente che:

Reader reader = new InputStreamReader(conn.getInputStream(), "UTF-8"); 
    StringBuilder buffer = new StringBuilder(); 
    char[] tmp = new char[1024]; 
    int l; 
    while((l = reader.read(tmp)) != -1) { 
     buffer.append(tmp, 0, l); 
    } 
    responseString = buffer.toString();