Jsoup 将 & 转换为 & 当我需要该信息时

Pok*_*uri 6 java jsoup

在少数情况下,我传递具有用户执行某些操作的页面 url 的 JSON。该页面 url 将包含我需要的那些查询字符串部分,以便用户在我的应用程序需要时重定向到同一页面。我的 JSON 会像

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

但是当我运行这个 json 时,Jsoup.clean(json, Whitelist.basic())我看到它&被替换为&. 我可以配置Jsoup为不单独转义此字符吗?

Alk*_*ris 6

转义发生在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(';');
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

一种快速完成您需要的方法是使用这样的东西

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);
Run Code Online (Sandbox Code Playgroud)

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


Pok*_*uri 4

作为应用后的解决方法,Jsoup.clean()我将替换&amp;&using regex

String url = Jsoup.clean(url, Whitelist.basic()).replaceAll("&amp;", "&");
Run Code Online (Sandbox Code Playgroud)

  • 你应该使用replace()而不是replaceAll(),因为replaceAll()使用正则表达式和“&amp;” 不是正则表达式,而是字符序列/sf/answers/757953031/ (2认同)