在 JSON 我该如何逃避字符串?

在手动创建 JSON 数据时,如何转义字符串字段?我应该使用 Apache Commons Lang 的 StringEscapeUtilities.escapeHtmlStringEscapeUtilities.escapeXml还是应该使用 java.net.URLEncoder

问题是,当我使用 SEU.escapeHtml时,它不转义引号,当我将整个字符串包装在一对 '中时,将生成一个格式不正确的 JSON。

478317 次浏览

理想情况下,您可以将一些适当的数据结构提供给 在您的语言中找到一个 JSON 库,即 让它担心如何逃避。这会让你保持清醒。如果由于某种原因您的语言中没有库,您不想使用它(我不建议这样做) ,或者您正在编写一个 JSON 库,请继续阅读。

根据 RFC 逃脱它。JSON 是相当开放的: 必须的转义的唯一字符是 \"和控制代码(任何小于 U + 0020的字符)。

这种转义结构是特定于 JSON 的。您将需要一个特定于 JSON 的函数。所有转义都可以写成 \uXXXX,其中 XXXX是该字符的 UTF-16代码 unit1。有一些快捷方式,例如 \\,也可以工作。(它们的结果是产出更小、更清晰。)

有关详细信息,请参阅 RFC

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

不确定“手动创建 JSON”是什么意思,但是您可以使用类似 gson (http://code.google.com/p/google-gson/)的东西,这将把您的 HashMap、 Array、 String 等转换为 JSON 值。我建议为此使用一个框架。

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

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

我还没有花时间去做100% 的确定,但是它对我的输入足够有效,可以被在线 JSON 验证器接受:

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

尽管它看起来并不比 org.codehaus.jettison.json.JSONObject.quote("your string")

我只是在我的项目中使用速度工具-我的“手动 JSON”构建在速度模板中

Escape ()转义引号、/、 r、 n、 b、 f、 t 和其他控制字符。它可以用来转义 JavaScript 代码。

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

摘自 弃船:

 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();
}

StringEscapeUtils.escapeJavaScript/StringEscapeUtils.escapeEcmaScript也可以。

现在在 Apache 公共文本库中有一个 StringEscapeUtils # escape eJson (String)方法。

感兴趣的方法如下:

这个功能最初作为 Apache Commons Lang版本3.2的一部分发布,但后来已被弃用并转移到了 Apache 公共文本。因此,如果在 IDE 中将该方法标记为已弃用,那么就是从错误的库导入了实现(两个库使用相同的类名: StringEscapeUtils)。

这个实现并不是纯粹的 Json:

使用 JsonString 规则转义 String 中的字符。

转义它在 JsonString 表单中找到的任何值 正确地使用引号和 control-chars (tab、反斜杠、 cr、 ff 等)

因此制表符就变成了字符’和’t’。

Java 字符串和 Json 字符串之间的唯一区别是 Json,转义了正斜杠(/)。

详情请参阅 http://www.ietf.org/rfc/rfc4627.txt

对于那些来这里寻找命令行解决方案的人,比如我,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 的教程: -)

在 commons lang API 中使用 EscapeUtils 类。

EscapeUtils.escapeJavaScript("Your JSON string");

考虑 莫希JsonWriter类。它有一个很棒的 API,它将复制减少到最低限度,所有东西都可以很好地流到一个文件,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();

如果你想把绳子放在手里:

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

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

承蒙单一项目的好意@ Https://github.com/mono/mono/blob/master/mcs/class/System

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();
}
}

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

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

文件摘录:

将数据编码为 JSON 字符串。 这将应用引号和任何必要的字符转义。[ ... ] Null 将被解释为空字符串

如果您正在使用 fastexml jackson,可以使用以下命令: com.fasterxml.jackson.core.io.JsonStringEncoder.getInstance().quoteAsString(input)

如果你正在使用 codehaus jackson,你可以使用以下命令: org.codehaus.jackson.io.JsonStringEncoder.getInstance().quoteAsString(input)

如果您需要在 JSON 字符串中转义 JSON,那么使用 org.JSON.JSONObject.quote (“ your JSON string that need to be escape”)似乎可以很好地工作

使用 uXXXX 语法可以解决这个问题,谷歌 UTF-16与名称的符号,你可以找出 XXXX,例如: utf-16双引号

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

Apache commons-text 现在有一个 StringEscapeUtils.escapeJson (String) .