我应该如何在JSON中转义string?

当手动创buildJSON数据时,我应该如何转义string字段? 我应该使用像Apache Commons Lang的StringEscapeUtilities.escapeHtmlStringEscapeUtilities.escapeXml ,还是应该使用java.net.URLEncoder

问题是,当我使用SEU.escapeHtml ,它不会避免引号,当我把整个string包装成一对的时候,会产生格式不正确的JSON。

理想情况下, 用您的语言find一个JSON库 ,您可以提供一些适当的数据结构, 让它担心如何逃避 。 它会让你更安心。 如果因为某种原因你没有使用你的语言库,你不想使用它(我不会build议这个¹),或者你正在编写一个JSON库,请继续阅读。

根据RFC转义它。 JSON非常自由:唯一必须转义的字符是\"和控制代码(任何小于U + 0020的字符)。

这种转义结构特定于JSON。 你需要一个JSON特定的function。 所有的转义符都可以写为\uXXXX ,其中XXXX是该字符的UTF-16编码单元1。 有几个快捷方式,如\\ ,也可以。 (而且它们导致更小和更清晰的输出。)

有关完整的详细信息,请参阅RFC 。

¹JSON的转义是build立在JS上的,所以它使用\uXXXX ,其中XXXX是一个UTF-16编码单元。 对于BMP之外的代码点,这意味着编码代理对,这可能会有点毛毛。 (或者,你可以直接输出字符,因为JSON的编码是Unicode文本,并允许这些特定的字符。)

从Jettison中提取:

  public static String quote(String string) { if (string == null || string.length() == 0) { return "\"\""; } char c = 0; int i; int len = string.length(); StringBuilder sb = new StringBuilder(len + 4); String t; sb.append('"'); for (i = 0; i < len; i += 1) { c = string.charAt(i); switch (c) { case '\\': case '"': sb.append('\\'); sb.append(c); break; case '/': // if (b == '<') { sb.append('\\'); // } sb.append(c); break; case '\b': sb.append("\\b"); break; case '\t': sb.append("\\t"); break; case '\n': sb.append("\\n"); break; case '\f': sb.append("\\f"); break; case '\r': sb.append("\\r"); break; default: if (c < ' ') { t = "000" + Integer.toHexString(c); sb.append("\\u" + t.substring(t.length() - 4)); } else { sb.append(c); } } } sb.append('"'); return sb.toString(); } 

试试这个org.codehaus.jettison.json.JSONObject.quote("your string")

从这里下载: http : //mvnrepository.com/artifact/org.codehaus.jettison/jettison

org.json.simple.JSONObject.escape()转义引号,\,/,\ r,\ n,\ b,\ f,\ t和其他控制字符。 它可以用来逃避JavaScript代码。

 import org.json.simple.JSONObject; String test = JSONObject.escape("your string"); 

Apache commons lang现在支持这个。 只要确保你的类path中有最新版本的Apache commons lang。 你将需要版本3.2 +

版本3.2的发行说明

LANG-797:添加了escape / unescapeJson到StringEscapeUtils。

StringEscapeUtils.escapeJavaScript / StringEscapeUtils.escapeEcmaScript应该这样做。

org.json.JSONObject quote(String data)方法完成这个工作

 import org.json.JSONObject; String jsonEncodedString = JSONObject.quote(data); 

从文档中提取:

将数据编码为JSONstring。 这适用于引号和任何必要的字符转义 。 […] Null将被解释为空string

不知道你的意思是“手动创buildjson”,但你可以使用像gson( http://code.google.com/p/google-gson/ ),这将改变你的HashMap,数组,string等,到一个JSON值。 我build议与此框架。

在commons lang API中使用EscapeUtils类。

 EscapeUtils.escapeJavaScript("Your JSON string"); 

我没有花时间做100%的确定,但它的工作足以让我的投入被在线JSONvalidation器接受:

 org.apache.velocity.tools.generic.EscapeTool.EscapeTool().java("input") 

虽然它看起来没有比org.codehaus.jettison.json.JSONObject.quote("your string")更好

我只是在我的项目中使用速度工具 – 我的“手动JSON”build筑是在一个速度模板

对于那些来我这里寻找命令行解决scheme的人来说,cURL的–data-urlencode工作正常:

 curl -G -v -s --data-urlencode 'query={"type" : "/music/artist"}' 'https://www.googleapis.com/freebase/v1/mqlread' 

发送

 GET /freebase/v1/mqlread?query=%7B%22type%22%20%3A%20%22%2Fmusic%2Fartist%22%7D HTTP/1.1 

, 例如。 较大的JSON数据可以放在一个文件中,你可以使用@语法来指定一个文件来唾弃来自要转义的数据。 例如,如果

 $ cat 1.json { "type": "/music/artist", "name": "The Police", "album": [] } 

你会用

 curl -G -v -s --data-urlencode query@1.json 'https://www.googleapis.com/freebase/v1/mqlread' 

现在,这也是一个关于如何从命令行查询Freebase的教程:-)

考虑Moshi的JsonWriter类。 它有一个非常棒的API,它将拷贝减less到最低限度,一切都可以很好地传输到一个文件,OutputStream等等。

 OutputStream os = ...; JsonWriter json = new JsonWriter(Okio.buffer(Okio.sink(os))); json.beginObject(); json.name("id").value(getId()); json.name("scores"); json.beginArray(); for (Double score : getScores()) { json.value(score); } json.endArray(); json.endObject(); 

如果你想要手中的string:

 Buffer b = new Buffer(); // okio.Buffer JsonWriter writer = new JsonWriter(b); //... String jsonString = b.readUtf8(); 

如果您使用的是紧固件jackson,则可以使用以下命令: com.fasterxml.jackson.core.io.JsonStringEncoder.getInstance().quoteAsString(input)

如果您使用的是codehaus jackson,则可以使用以下代码: org.codehaus.jackson.io.JsonStringEncoder.getInstance().quoteAsString(input)

如果您需要在JSONstring内部转义JSON,请使用org.json.JSONObject.quote(“您需要转义的jsonstring”)似乎工作正常

使用\ uXXXX语法就可以解决这个问题,用UTF-16的google的名字签名,就可以找出XXXX了,例如:utf-16双引号

这里显示实际执行的方法都是错误的。
我没有Java代码,但只是为了logging,你可以很容易地转换这个C#代码:

感谢mono-project @ https://github.com/mono/mono/blob/master/mcs/class/System.Web/System.Web/HttpUtility.cs

 public static string JavaScriptStringEncode(string value, bool addDoubleQuotes) { if (string.IsNullOrEmpty(value)) return addDoubleQuotes ? "\"\"" : string.Empty; int len = value.Length; bool needEncode = false; char c; for (int i = 0; i < len; i++) { c = value[i]; if (c >= 0 && c <= 31 || c == 34 || c == 39 || c == 60 || c == 62 || c == 92) { needEncode = true; break; } } if (!needEncode) return addDoubleQuotes ? "\"" + value + "\"" : value; var sb = new System.Text.StringBuilder(); if (addDoubleQuotes) sb.Append('"'); for (int i = 0; i < len; i++) { c = value[i]; if (c >= 0 && c <= 7 || c == 11 || c >= 14 && c <= 31 || c == 39 || c == 60 || c == 62) sb.AppendFormat("\\u{0:x4}", (int)c); else switch ((int)c) { case 8: sb.Append("\\b"); break; case 9: sb.Append("\\t"); break; case 10: sb.Append("\\n"); break; case 12: sb.Append("\\f"); break; case 13: sb.Append("\\r"); break; case 34: sb.Append("\\\""); break; case 92: sb.Append("\\\\"); break; default: sb.Append(c); break; } } if (addDoubleQuotes) sb.Append('"'); return sb.ToString(); } 

这可以压缩成

  // https://github.com/mono/mono/blob/master/mcs/class/System.Json/System.Json/JsonValue.cs public class SimpleJSON { private static bool NeedEscape(string src, int i) { char c = src[i]; return c < 32 || c == '"' || c == '\\' // Broken lead surrogate || (c >= '\uD800' && c <= '\uDBFF' && (i == src.Length - 1 || src[i + 1] < '\uDC00' || src[i + 1] > '\uDFFF')) // Broken tail surrogate || (c >= '\uDC00' && c <= '\uDFFF' && (i == 0 || src[i - 1] < '\uD800' || src[i - 1] > '\uDBFF')) // To produce valid JavaScript || c == '\u2028' || c == '\u2029' // Escape "</" for <script> tags || (c == '/' && i > 0 && src[i - 1] == '<'); } public static string EscapeString(string src) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); int start = 0; for (int i = 0; i < src.Length; i++) if (NeedEscape(src, i)) { sb.Append(src, start, i - start); switch (src[i]) { case '\b': sb.Append("\\b"); break; case '\f': sb.Append("\\f"); break; case '\n': sb.Append("\\n"); break; case '\r': sb.Append("\\r"); break; case '\t': sb.Append("\\t"); break; case '\"': sb.Append("\\\""); break; case '\\': sb.Append("\\\\"); break; case '/': sb.Append("\\/"); break; default: sb.Append("\\u"); sb.Append(((int)src[i]).ToString("x04")); break; } start = i + 1; } sb.Append(src, start, src.Length - start); return sb.ToString(); } } 

我认为2017年的最佳答案是使用javax.json API。 使用javax.json.JsonBuilderFactory创build您的json对象,然后使用javax.json.JsonWriterFactory写出对象。 非常好的build设者/作家组合。