Jsoup将“&”转换为“&”,而我需要保留原始信息。

7

有时我会传递JSON,其中包含用户执行某些操作的页面URL。该页面URL将具有查询字符串部分,我需要它以便在需要时从我的应用程序重定向用户到同一页面。我的JSON将如下所示:

{
"userId":"123456789",
"pageUrl":"http://exampl.com/designs.jsp?templateId=f348aaf2-45e4-4836-9be4-9a7e63105932&kind=123",
"action":"favourite"
}

但是,当我将这个json通过Jsoup.clean(json, Whitelist.basic())运行时,我发现&被替换为&。我能否配置Jsoup不仅不转义这个字符?


你尝试过其他白名单选项吗,比如relaxed - Makoto
即使放松了,我仍然看到相同的结果。 - Pokuri
2个回答

8

转义过程发生在org.jsoup.nodes.Entities。以下是相关代码:

static void escape(StringBuilder accum, String string,
        Document.OutputSettings out, boolean inAttribute,
        boolean normaliseWhite, boolean stripLeadingWhite) {
    boolean lastWasWhite = false;
    boolean reachedNonWhite = false;
    EscapeMode escapeMode = out.escapeMode();
    CharsetEncoder encoder = out.encoder();
    CoreCharset coreCharset = CoreCharset.access$300(encoder.charset().name());
    Map map = escapeMode.getMap();
    int length = string.length();
    int codePoint;
    for (int offset = 0; offset < length; offset += Character.charCount(codePoint)) {
        codePoint = string.codePointAt(offset);

        if (normaliseWhite) {
            if (StringUtil.isWhitespace(codePoint)) {
                if ((stripLeadingWhite) && (!(reachedNonWhite)))
                    continue;
                if (lastWasWhite)
                    continue;
                accum.append(' ');
                lastWasWhite = true;
                continue;
            }
            lastWasWhite = false;
            reachedNonWhite = true;
        }

        if (codePoint < 65536) {
            char c = (char) codePoint;

            switch (c) {
            case '&':
                accum.append("&amp;");
                break;
            case ' ':
                if (escapeMode != EscapeMode.xhtml)
                    accum.append("&nbsp;");
                else
                    accum.append(c);
                break;
            case '<':
                if (!(inAttribute))
                    accum.append("&lt;");
                else
                    accum.append(c);
                break;
            case '>':
                if (!(inAttribute))
                    accum.append("&gt;");
                else
                    accum.append(c);
                break;
            case '"':
                if (inAttribute)
                    accum.append("&quot;");
                else
                    accum.append(c);
                break;
            default:
                if (canEncode(coreCharset, c, encoder))
                    accum.append(c);
                else if (map.containsKey(Character.valueOf(c)))
                    accum.append('&')
                            .append((String) map.get(Character.valueOf(c)))
                            .append(';');
                else
                    accum.append("&#x")
                            .append(Integer.toHexString(codePoint))
                            .append(';');
            }
        } else {
            String c = new String(Character.toChars(codePoint));
            if (encoder.canEncode(c))
                accum.append(c);
            else
                accum.append("&#x").append(Integer.toHexString(codePoint))
                        .append(';');
        }
    }
}

快速完成您所需的方法是使用类似以下内容的东西

String str = "http://exampl.com/designs.jsp?templateId=f348aaf2-45e4-4836-9be4-9a7e63105932&kind=123";
str = Jsoup.clean(str, Whitelist.basic());
System.out.println(str);
str = Parser.unescapeEntities(str, true);
System.out.println(str);

另一种方法是扩展上述类并覆盖导致问题的方法,但由于该方法仅对包(默认可见性)可见,这意味着您必须下载源代码,更改上述方法的可见性后再覆盖该类(以使该方法可见)。


感谢您的帮助。在应用Jsoup.clean()后,我正在使用正则表达式将&替换为&作为解决方法。 - Pokuri
1
我相信这是一种更安全的做法,但如果这解决了你的问题,那就尽管使用吧。既然我的答案没有解决你的问题,请发布你自己的答案并选择它,以便问题可以被视为已关闭。 - Alkis Kalogeris
使用 Parser.unescapeEntities(str, true) 比使用正则表达式替换更安全。 - Jamith NImantha
1
非常感谢您的回答,@AlkisKalogeris。这为我节省了很多时间。 - Jean-François Côté

4
在应用了Jsoup.clean()后,我通过使用regex&amp;替换为&来解决问题。
String url = Jsoup.clean(url, Whitelist.basic()).replaceAll("&amp;", "&");

2
你应该使用replace()而不是replaceAll(),因为replaceAll()使用正则表达式,而"&"不是正则表达式,而是一个字符序列。 - Jamith NImantha

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