我正在使用Java来解析此请求
结果这个(为了简洁而截断)JSON文件:
{"responseData":{"results":
<...>
"visibleUrl":"www.coolcook.net",
"cacheUrl":"http://www.google.com/search?q\u003dcache:p4Ke5q6zpnUJ:www.coolcook.net",
"title":"مطبخ مطايب - كباب الدجاج والخضار بصلصة الروب",
"titleNoFormatting":"مطبخ مطايب - كباب الدجاج والخضار بصلصة الروب","\u003drz+img+news+recordid+border"}},
<...>
"responseDetails": null, "responseStatus": 200}
我的问题在于返回的阿拉伯字符(可能是任何非unicode)。我尝试使用类似的东西将它们转换回unicode:
JSONArray ja = json.getJSONObject("responseData").getJSONArray("results");
JSONObject j = ja.getJSONObject(i);
str = j.getString("titleNoFormatting");
logger.log("before: " + str); // this is just my version of println
enc_str = new String (str.getBytes(), "UTF8");
logger.log("after: " + enc_str);
但是,'before'和'after'结果都是相同的:一组????,无论我是在服务器日志文件中还是在HTML页面中输出它们。还有另一种方法可以取回阿拉伯字符并将其输出到网页中吗?
对于这类问题,JSON是否有任何支持功能可能是为了直接从JSONObject读取非utf字符?
答案 0 :(得分:7)
您遇到的问题很可能是由于您在谷歌的http响应中读取的字符编码设置不正确造成的。你可以发布实际获取URL的代码并将其解析为JSON对象吗?
作为示例运行以下内容:
public class Test1 {
public static void main(String [] args) throws Exception {
// just testing that the console can output the correct chars
System.out.println("\"title\":\"مطبخ مطايب - كباب الدجاج والخضار بصلصة الروب");
URL url = new URL("http://ajax.googleapis.com/ajax/services/search/web?start=0&rsz=large&v=1.0&q=rz+img+news+recordid+border");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream is = connection.getInputStream();
// the important bit is here..........................\/\/\/
InputStreamReader reader = new InputStreamReader(is, "utf-8");
StringWriter sw = new StringWriter();
char [] buffer = new char[1024 * 8];
int count ;
while( (count = reader.read(buffer)) != -1){
sw.write(buffer, 0, count);
}
System.out.println(sw.toString());
}
}
这是使用自时间开始以来一直存在的相当难看的标准URL.openConnection()
。如果你使用的是Apache httpclient之类的东西,那么你可以很容易地做到这一点。
关于编码的一些背景阅读,并且可能解释为什么new String (str.getBytes(), "UTF8");
将永远无法工作阅读Joel's article on unicode
答案 1 :(得分:2)
我认为JSON.org Java JSON包无法处理UTF8,无论是作为UTF8字符传入还是实际传入\uXXXX
代码。我试过两个如下:
import org.json.
public class JsonTest extends TestCase {
public void testParseText() {
try {
JSONObject json1 = new JSONObject("{\"a\":\"\u05dd\"}"); // \u05dd is a Hebrew character
JSONObject json2 = new JSONObject("{\"a\":\"\\u05dd\"}"); // \u05dd is a Hebrew character
System.out.println(json1.toString());
System.out.println(json2.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
}
我明白了:
{"a":"?"}
{"a":"?"}
有什么想法吗?
答案 2 :(得分:1)
首先尝试这个:
str = j.getString("titleNoFormatting");
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("c:/test.txt"), "UTF-8"));
writer.write(str);
writer.close();
然后在记事本中打开文件。如果这看起来很好,那么问题在于您的记录器或控制台没有配置为使用UTF-8
。否则问题很可能在于您使用的JSON API,它未配置为使用UTF-8
。
编辑:如果问题实际上在您使用的JSON API中,而您不知道选择哪个,那么我建议您使用Gson。它真的很容易将Json字符串转换为易于使用的javabean。这是一个基本的例子:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.List;
import com.google.gson.Gson;
public class Test {
public static void main(String[] args) throws Exception {
URL url = new URL("http://ajax.googleapis.com/ajax/services/search/web"
+ "?start=0&rsz=large&v=1.0&q=rz+img+news+recordid+border");
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
GoogleResults results = new Gson().fromJson(reader, GoogleResults.class);
// Show all results.
System.out.println(results);
// Show title of 1st result (is arabic).
System.out.println(results.getResponseData().getResults().get(0).getTitle());
}
}
class GoogleResults {
ResponseData responseData;
public ResponseData getResponseData() { return responseData; }
public void setResponseData(ResponseData responseData) { this.responseData = responseData; }
public String toString() { return "ResponseData[" + responseData + "]"; }
static class ResponseData {
List<Result> results;
public List<Result> getResults() { return results; }
public void setResults(List<Result> results) { this.results = results; }
public String toString() { return "Results[" + results + "]"; }
}
static class Result {
private String url;
private String title;
public String getUrl() { return url; }
public String getTitle() { return title; }
public void setUrl(String url) { this.url = url; }
public void setTitle(String title) { this.title = title; }
public String toString() { return "Result[url:" + url +",title:" + title + "]"; }
}
}
它可以很好地输出结果。希望这会有所帮助。
答案 3 :(得分:1)
问题的重要部分是如何处理HTTP响应的内容。也就是说,你是如何创建json
对象的?当您到达原始帖子中的代码时,内容已经损坏。
请求产生UTF-8编码数据。你是如何将其解析为JSON对象的?是否为解码器指定了正确的编码?或者您的平台使用默认字符编码?
答案 4 :(得分:1)
有一个library使用这样的JSon消息保留了http响应(捷克语表达式)的编码:
private static String inputStreamToString(final InputStream inputStream) throws Exception {
final StringBuilder outputBuilder = new StringBuilder();
try {
String string;
if (inputStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
while (null != (string = reader.readLine())) {
outputBuilder.append(string).append('\n');
}
}
} catch (Exception ex) {
throw new Exception("[google-api-translate-java] Error reading translation stream.", ex);
}
return outputBuilder.toString();
}
答案很棘手,必须注意几点,主要是平台编码:
afaik影响打印到控制台,从输入流创建文件甚至DB客户端和服务器之间的通信,即使它们都设置为使用utf-8字符集进行编码 - 无论我是否显式创建utf-8字符串,inputstreamReader或者为UTF-8设置JDBC驱动程序,仍然在Linux系统上将$ LANG属性设置为xx_XX.UTF-8,并将附加=“vt.default_utf8 = 1”添加到LILO引导加载程序(在使用它的系统上),必须完成至少对于运行使用utf-8编码文件的数据库和java应用程序的系统。
即使我附加了这个JVM参数-Dfile.encoding = UTF-8,没有平台编码,我在正确编码的流中也没有成功。正确设置JDBC连接器是必要的:“jdbc:mysql:// localhost / DBname?useUnicode = true&amp; characterEncoding = UTF8”,如果要将字符串保存到数据库,该数据库应该处于以下状态:
mysql> SHOW VARIABLES LIKE 'character\_set\_%';
+--------------------------+--------+
| Variable_name | Value |
+--------------------------+--------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
+--------------------------+--------+
答案 5 :(得分:0)
Google API正确发送UTF-8。我认为问题是您的默认编码无法输出阿拉伯语。检查您的file.encoding
媒体资源或获取此类编码,
public static String getDefaultCharSet() throws IOException {
OutputStreamWriter writer = new OutputStreamWriter(new ByteArrayOutputStream());
return writer.getEncoding();
}
如果默认编码是ASCII或Latin-1,您将获得“?”。您需要将其更改为UTF-8。