Java - Umlaute werden nicht korrekt angezeigt

ReqonxS

Mitglied
Ich habe eine Android Applikation programmiert und habe das Problem, dass zum Beispiel der Benutzername statt "Hüma" als "HA1/4ma" oder so angezeigt wird.
Woran kann es liegen?
Java:
JSONArray cast = json.getJSONArray("friends");
for (int i = 0; i < cast.length(); i++) {
    JSONObject actor = cast.getJSONObject(i);
    String fullname = actor.getString("fullname");
    String country = actor.getString("country");
    String profile_image = actor.getString("profile_image");
    sList.add(new Data(fullname, country, profile_image));
}
Das Ergebnis was PHP liefert:
Java:
{ "friends": [{ "fullname": "Dämö", "country": "Germany", "profile_image": "demo.png" } ]}
 
Hi,

ich denke mal, dass PHP die Strings in der ISO-8859 Kodierung ausgibt, schau mal, ob du die auf UTF-8 bekommst. (Im Editor, z.B. Notepad++ das PHP-Script aufmachen und als UTF-8 ohne BOM speichern)

Grüße,
BK
 
Das ist ganz klar ein Encoding-Fehler.

Nicht nur das, was Bratkartoffel geschrieben hat, ist wichtig, sondern auch, dass dein PHP-Skript die Daten wirklich als UTF-8 ausgibt und ein entsprechender HTTP-Header (Content-Type: text/html; charset=utf-8) mitgesendet wird. Es darauf geachtet werden, dass die die Daten bei der Ausgabe auch im UTF8-Encoding vorliegen. Ein Header allein reicht natürlich nicht.

Siehe auch: http://www.w3.org/International/O-HTTP-charset
 
Hmm,

laut Manual lässt json_encode() keine Konvertierung von nicht-utf8-Zeichenketten zu:

value
Der zu kodierende value. Kann von jedem Typ außer Ressource sein.


Alle Strings müssen in UTF-8 kodiert sein-

Das bedeutet, dass PHP-Script ist in UTF-8 gespeichert. Also bleibt nur die Variante, dass der HTTP-Header in ISO gesendet wird, mit UTF-8-Zeichen - dachte ich zunächst. Also habe ich mich mal hingesetzt und versucht, das Verhalten nachzustellen, ganz so einfach scheint es nicht zu sein.

1. Der Hinweis mit UTF-8 als Header klingt zunächst vielversprechend, ist aber nicht die Lösung, denn json_encode() gibt standardmäßig escapede UTF-8-Zeichen aus, das heißt, im String steht bspw. \u00ea. Damit da kein escaptes Zeichen zurück kommt, muss der Parameter $options auf JSON_UNESCAPED_UNICODE stehen. Ansonsten wäre das gesendete Encoding egal, es kämen ohnehin nur Zeichen aus dem 7-Bit-ASCII-Bereich zurück.

2. Der Hinweis mit Script als Unicode ohne BOM: Könnte es sein, kommt auf die verwendete JSON-Library an. Ich habe json-simple verwendet. Die wirft beim Parsen eine ParseException (Unexpected character () at position 0) sobald eine BOM im Script ist. Das wäre aber mal Wert überprüft zu werden. Ich weiß ja jetzt nicht, welche Library du genau verwendest, also wie Bratkartoffel schrieb, überprüf mal die BOM-Variante (also PHP-Script ohne BOM).

3. Ich habe natürlich die anderen Optionen (JSON_HEX_TAG, JSON_HEX_APOS, JSON_HEX_QUOT, JSON_HEX_AMP und alle zusammen als Bit-Maske) ausprobiert und konnte das Verhalten nicht nachstellen.

4. Ich habe absichtlich mein Java-Programm mal auf ISO-8859-1 (in der Eclipse) umgestellt, möglicherweise ist deine Eclipse sogar auf CP1252 im Workspace-Encoding eingestellt, und damit erben die Projekte erstmal diese Einstellung, solange du die Projekte nicht dazu zwingst, ein spezifisches Encoding (z.B. UTF-8) zu verwenden. Jedenfalls habe ich dann ein ähnliches Phänomen beobachtet, bei mir kam dann der String

Code:
Dämö

zurück. Prüfe also die Encoding-Einstellung in deinem Java-Projekt.



Mein Fazit: Das Script sollte ohne BOM und UTF-8-encodet sein. json_encode() solltest du ggf. mit JSON_UNESCAPED_UNICODE aufrufen, und den Header so senden:

PHP:
   header('Content-Type: application/json;');
   header('Content-Length: ' . strlen($content));
   echo $content;

Außerdem solltest du sicherstellen, das dein Java-Programm in UTF-8 gespeichert ist. Am besten ist es ohnehin, wenn alle Resourcen, die irgendwie im Internet kommunizieren auf UTF-8 eingestellt zu sein und auch in Unicode untereinander kommunizieren.


Hier meine komplette Test-Suite:

Java:
package jsontest;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

public class JsonTest
{
  private void parse(String jsonString) throws Exception
  {
    JSONParser parser = new JSONParser();
    JSONObject json = (JSONObject) parser.parse(jsonString);
    JSONArray friends = (JSONArray) json.get("friends");

    for (int i = 0; i < friends.size(); i++)
    {
      JSONObject actor = (JSONObject) friends.get(i);
      String fullname = (String) actor.get("fullname");

      System.out.println(fullname);
    }
  }

  private String retrieveJson(String url) throws Exception
  {
    return this.retrieveJson(new URL(url));
  }

  private String retrieveJson(URL url) throws Exception
  {
    StringBuilder sb = new StringBuilder();

    InputStream is = url.openStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader reader = new BufferedReader(isr);
    String line;
    while ((line = reader.readLine()) != null)
    {
      sb.append(line);
    }

    return sb.toString();
  }

  public static void main(String[] args)
  {
    try
    {
      JsonTest instance = new JsonTest();
      instance.parse(instance.retrieveJson("http://localhost/tests/json.php"));
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
      System.exit(-1);
    }

    System.exit(0);
  }
}

PHP:
<?php
ini_set('display_errors', 1);
error_reporting(-1);

$out = array();

$friend = new stdClass();
$friend->fullname = "Dämö";
$friend->country = "Germany";
$friend->profile_image = "demo.png";

$out['friends'][] = $friend;

$content = json_encode($out, JSON_UNESCAPED_UNICODE);

if(json_last_error() == 0)
{
   header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
   header('Cache-Control: post-check=0, pre-check=0', false);
   header('Content-Type: application/json;');
   header('Content-Length: ' . strlen($content));
   echo $content;
}
else
{
   header('HTTP/1.1 500 Internal Server Error');
   echo json_last_error_msg();
}
 
Zurück