String字符串特殊字符强制不转义
场景介绍:
前端页面JSP(其它同理)需要输入一系列的数据,传到后台,后台校验和拼装数据以Http的方式调用RestHub接口,接口的参数是JSON字符串。
问题描述:
现在JSP页面输入一些特殊字符,比如:……(中文的省略号)、""(英文的双引号)传到后台后会自动转义。……(中文的省略号)转义为……、""(英文的双引号)转义为""
现象如下图所示:
其实转义之后,在调用RestHub接口也能调用成功,数据库里存储的数据也是那些转义了的字符,JSP页面查看的时候也能再转义回来,正常的显示中文的省略号和英文的双引号,在我测试的过程中也注意到了特殊符号的测试,当时也看到了这个问题,但是页面能正常显示出来,也就没放心上。之后在生产环境中有客户用APP(IOS)查看数据时,那些特殊符号没有自动转义回来,后来咨询IOS的同事,他说IOS用的是label而非HTML那套东西,所以他那边并没有那般智能的转义,而是从后台拿到什么数据就渲染到页面label中。所以那些特殊字符必须不能让他自动转义了。
解决方案:
最初想到的方案是针对特殊的字段做处理,但是接口中要传的数据太多了,无法一个一个处理,只能对整个JSON字符串统一的处理。
org.apache.commons.lang.StringEscapeUtils工具类(JAR源码位置(注意版本 ))里有unescapeHtml(String param)可以不转义字符串。
本类文件里还有一些其它的关于特殊符号的处理方法,比如escapeJava、unescapeJava、escapeJavaScript、unescapeJavaScript、unescapeCsv、escapeCsv、unescapeXml、escapeXml等等,commons-lang3-3.1(JAR包和源码位置)版本的jar包还有其它的处理方法如escapeHtml3、unescapeHtml3、escapeHtml4、unescapeHtml4
结果如图:
将源码贴出
public static String escapeHtml(String str) { if (str == null) { return null; } try { StringWriter writer = new StringWriter ((int)(str.length() * 1.5)); escapeHtml(writer, str); return writer.toString(); } catch (IOException ioe) { //should be impossible throw new UnhandledException(ioe); } }
public static void escapeHtml(Writer writer, String string) throws IOException { if (writer == null ) { throw new IllegalArgumentException ("The Writer must not be null."); } if (string == null) { return; } Entities.HTML40.escape(writer, string); }
继续测试,又发现其它问题,如果我输入框中只输入英文的双引号,直接导致后台抛异常net.sf.json.JSONException: Expected a "," or "}"
debug查看JSON字符串如下图所示
其实,上述不应该算是JSON字符串了,JSON字符串的格式应该是{key:value},例如{“name”: "张三"},而上图是{"name":""张三""}有了两个双引号,根本不是JSON字符串。
所以要想办法把value中的英文双引号转换成中文双引号
方法如下:
public static String jsonString(String s) { char[] temp = s.toCharArray(); int n = temp.length; for (int i =0; i<n; i++) { if (temp[i] == ":" && temp[i+1] == """) { for (int j = i+2; j<n; j++) { if (temp[j] == """) { if (temp[j+1] != "," && temp[j+1] != "}") { temp[j] = "”"; } else if(temp[j+1] =="," || temp[j+1] == "}") { break; } } } } } return new String(temp); }到此,问题解决。