从字符串中移除所有的 \ 符号。

26

我正在尝试使用JSON从服务器获取对象数组。

服务器向我发送以下字符串。

"[{\"DealComment\":null,\"DealVotes\":[],\"DealId\":1,\"CompanyId\":1,\"StartDate\":\"2012-12-13T00:00:00\",\"EndDate\":\"2012-12-16T00:00:00\",\"CouponCode\":\"Test Coupon 1\",\"Description\":\"Test Deal Description 1\",\"VoteUp\":null,\"VoteDown\":null,\"ViewCount\":null,\"Title\":\"Test Deal 1\"},{\"DealComment\":null,\"DealVotes\":[],\"DealId\":2,\"CompanyId\":1,\"StartDate\":\"2012-12-16T00:00:00\",\"EndDate\":\"2012-12-17T00:00:00\",\"CouponCode\":\"Test Coupon 2\",\"Description\":\"Test Description 2\",\"VoteUp\":null,\"VoteDown\":null,\"ViewCount\":null,\"Title\":\"Test Deal 2\"},{\"DealComment\":null,\"DealVotes\":[],\"DealId\":3,\"CompanyId\":1,\"StartDate\":\"2012-12-14T00:00:00\",\"EndDate\":\"2012-12-15T00:00:00\",\"CouponCode\":\"Test Code 3\",\"Description\":\"Test Description 3\",\"VoteUp\":null,\"VoteDown\":null,\"ViewCount\":null,\"Title\":\"Test Deal 3\"},{\"DealComment\":null,\"DealVotes\":[],\"DealId\":4,\"CompanyId\":1,\"StartDate\":\"2012-12-12T00:00:00\",\"EndDate\":\"2012-12-13T00:00:00\",\"CouponCode\":\"Test Coupon 4\",\"Description\":\"Test Description 4\",\"VoteUp\":null,\"VoteDown\":null,\"ViewCount\":null,\"Title\":\"Test Deal 4\"},{\"DealComment\":null,\"DealVotes\":[],\"DealId\":5,\"CompanyId\":2,\"StartDate\":\"2012-12-12T00:00:00\",\"EndDate\":\"2012-12-14T00:00:00\",\"CouponCode\":\"AwD\",\"Description\":\"Very awesome deal!\",\"VoteUp\":null,\"VoteDown\":null,\"ViewCount\":null,\"Title\":\"Awesome Deal 1\"}]"
现在,如果您仔细查看字符串,您会注意到它包含每个"\",该字符串目前无法格式化为JSONArray。因此,我需要将每个\"替换为",这本来是一项相当简单的任务,但是由于\是一个转义序列,所以需要注意。
我尝试使用以下代码。
String jsonFormattedString = jsonStr.replaceAll("\\", "");

但它会给我以下异常。

12-19 00:35:59.575: W/System.err(444): java.util.regex.PatternSyntaxException: Syntax error U_REGEX_BAD_ESCAPE_SEQUENCE near index 1:
12-19 00:35:59.575: W/System.err(444): \
12-19 00:35:59.575: W/System.err(444):  ^

我的全部代码,如果有用的话:

public void getAllDealsFromServerJson()
{

    String apiUrl = "http://passme.azurewebsites.net/api/TestApi/";


    HttpClient client = new DefaultHttpClient();
    HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000); //Timeout Limit
    HttpResponse response;
    JSONObject json = new JSONObject();

    try{
        HttpPost httpPost = new HttpPost(apiUrl);
        json.put("requestType", "getalldeals" );

        StringEntity se = new StringEntity( json.toString());  
        se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
        httpPost.setEntity(se);
        response = client.execute(httpPost);
        Log.d("Http Response:", response.toString());
        jsonResponse = response.toString();

        BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
        String jsonStr = reader.readLine();
        Log.d("String Response", jsonStr);
        String jsonFormattedString = jsonStr.replaceAll("\\", ""); // gives error
        Log.d("Formatted String", jsonFormattedString);
        //JSONTokener tokener = new JSONTokener(jsonFormattedString);
        /*JSONObject finalResult = new JSONObject(tokener);
        Log.d("JSON Response", "" + finalResult.optString("Title"));*/
        JSONArray resultArray = new JSONArray(jsonFormattedString);
        Log.d("JSON Array Result Length", "" + resultArray.length());
        Log.d("JSON Array Result ", "" + resultArray.getJSONObject(0).optInt("DealId"));

    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}
6个回答

48

试试这个:

String jsonFormattedString = jsonStr.replaceAll("\\\\", "");

由于反斜杠是正则表达式中的转义字符(replaceAll() 接收一个作为参数),所以它也必须被转义。


3
String jsonFormattedString = jsonStr.replace('\\', ''); 这样写更简单,因为你不需要双重转义。文档中说:返回一个新的字符串,其中所有出现在原字符串中的 oldChar 都被替换成 newChar。 - mike jones
1
@mikejones 如果你从问题中注意到,这就是原始提问者最初尝试的方法,但它并没有起作用。 - Hunter McMillen
3
不完全正确。OP正在使用replaceAll(String, String),而@mikejones建议使用replace(char, char)。(不幸的是,@mikejones的解决方案也不会起作用,因为没有“空字符”''。) - Louis Wasserman
1
@ÓscarLópez:非常有帮助!太棒了!好吧,SO让我等待另外6分钟才能点击接受标记。所以,我想我还需要6分钟才能接受它!:D - Swayam
8
这可能解决眼前的问题,但会在以后引发问题。我们假设反斜杠的唯一用途是作为双引号的前缀,在这个例子中或许是这样的。然而,根本原因是服务器对数据进行了两次 JSON 编码。如果不专门处理这个问题,你的代码存在一个隐藏的漏洞,当结果中有真正的反斜杠被意外删除时,这个漏洞会爆发。 - jimbo
显示剩余2条评论

16

实际上,正确的方式应该是:

String jsonFormattedString = jsonStr.replace("\\\"", "\"");
您希望仅将\"替换为",而不是将所有\替换为空(这将消耗您在json字符串中的斜杠,如果有的话)。 与普遍认为的相反,replace(...)也会替换给定字符串的所有出现,就像replaceAll(...)一样,只是它不使用正则表达式,因此通常更快。

哦,我不知道那个。但是把“\”替换成“"不是一样的吗? - Swayam
感谢您的帮助。 - Chirag Savsani
@Swayam 是的,如果我们假设给定的 JSON 不会在任何地方包含 \ - Krzysztof Krasoń
感谢澄清。现在阅读这篇文章让我想起了四年前的那个问题。 :) - Swayam
如果我们想在字符串中保留 \",它也会将其删除。 - NullByte08

11

只需使用:

try {
        jsonFormattedString = new JSONTokener(jsonString).nextValue().toString();
    } catch (JSONException e) {
        e.printStackTrace();
    }

请查看文档


4
正确的做法是不使用正则表达式或字符串替换“\.”。 - Soumya
2
这应该是正确的答案,通过替换方法可能会在JSON中出现其他格式问题。 - Ali Akram
1
大家好,请使用这个方法。谢谢。 - garish
1
这是最好的答案。 - Felipe Morais
这是org.json包中的一个类,它是JSON-java库的一部分。 - Alex Kucherenko
显示剩余2条评论

6

看起来你的输入字符串被双重JSON编码了。你应该先解码它,然后再次解码。

以下是我在Java中猜测如何完成此操作的最佳方法:

JSONArray resultArray = new JSONArray(new JSONString(jsonFormattedString));

我在这里假设JSONString是一种类型。你的实际解决方案可能会有所不同。

在正常情况下,我希望服务直接提供给您JSON数据。但是看起来这个服务提供给您一个字符串(按照JSON规范编码),其中包含JSON数据。

这就是以下两者之间的区别:

String someJSON = "[0, 1, 2]";
String doublyEncodedJSON = "\"[0, 1, 2]\"";

注意到了额外的引号吗?那是因为后面的字符串是JSON格式。要获得实际的对象,你需要解码两次。


我应该怎样做,先生? - Swayam
增加了我的最佳猜测---我不经常进行Java开发,但我每天都使用JSON。祝你好运! - jimbo
实际上先生,我只是将 " 替换为 ",然后在 http://www.jsoneditoronline.org/ 上测试了生成的字符串。它以我预期的方式正确显示出来了。 - Swayam
是的,我同意它适用于你目前从第三方 JSON 服务获取的特定示例数据。我在其他答案的评论中解释了这掩盖了一个隐藏的错误,当数据最终包含真正的反斜杠时,这个错误将会出现。 - jimbo
是的先生,我明白了。我会查看如何在Java中进行JSON双重解码。 - Swayam

6
您可以直接使用以下代码:
str.replace("\\","");

replace()函数使用字符串作为参数,replaceAll()函数则使用正则表达式。下面的代码也可以将字符串替换为另一个字符串:

str.replaceAll("\\\\", "");

谢谢你的回答。我使用了第一个答案,现在它可以工作了。无论如何还是非常感谢! :) - Swayam

1
jsonObj.toString()
        .replace("\"[", "[").replace("]\"", "]")
        .replace("\\\"{", "{").replace("}\\\"", "}")
        .replace("\\\\\\\"", "\"")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接