我想在Java中去除JSON字符串中的额外空格,但不想移除键和值中的字符间的空格。
实际的JSON字符串:
{ "Error" : "Invalid HTTP Method" , "ErrorCode" : "405" , "ErrorDesc" : "Method Not Allowed" }
所需的 JSON
{"Error":"Invalid HTTP Method","ErrorCode":"405","ErrorDesc":"Method Not Allowed"}
一个更简单而更安全的解决方案是使用 Gson库(只需要几行代码):
public static String simplify(String json) {
Gson gson = new GsonBuilder().create();
JsonElement el = JsonParser.parseString(json);
return gson.toJson(el);
}
你甚至可以通过Gson的漂亮输出选项,反转整个过程(添加空格):
public static String beautify(String json) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonElement el = JsonParser.parseString(json);
return gson.toJson(el);
}
我会选择类似这样的东西:
public static void main(String[] args) {
String json = "{ \"Error\": \"Inv\\\"alid HTTP Method\", \"ErrorCode\":\"405\",\"ErrorDesc\":\"Method Not Allowed\"}";
System.out.println(removeWhitespaces(json));
}
public static String removeWhitespaces(String json) {
boolean quoted = false;
boolean escaped = false;
String out = "";
for(Character c : json.toCharArray()) {
if(escaped) {
out += c;
escaped = false;
continue;
}
if(c == '"') {
quoted = !quoted;
} else if(c == '\\') {
escaped = true;
}
if(c == ' ' &! quoted) {
continue;
}
out += c;
}
return out;
}
测试运行返回
{"Error":"Invalid HTTP Method","ErrorCode":"405","ErrorDesc":"Method Not Allowed"}
let myjsonstr = '{"Error" : "Invalid Method", "ErrorCode" : 405, "ErrMsg" : "This \\"Thing\\" is not allowed" }';
类似的事情在Java中、从数据库中读取或由用户输入时同样容易发生。 - Stephen P\"
的情况,但也会导致其他一些问题;解析并不容易。如果在字符串中遇到 \t
会怎样?如果是 \\t
或者像我使用的 \\\"
又会怎样?很多字符在用反斜杠转义后都具有特殊的含义,而且不仅仅是“打印跟在反斜杠后面的字符”——比如,\t
应该被转换成制表符 0x09
。如果你只有一个有限而已知的输入集合,那么你的方法可能是安全的,这也可能是 OPs 的情况,但未来的读者可能会试图将此推广到一般情况,这就是我指出这一点的原因。 - Stephen P@Fabian Z说的可能可以用,但可以进行优化(你不需要先将整个字符串转换为字符数组来迭代它,而且你应该使用StringBuilder):
public static String removeWhitespaces(String json) {
boolean quoted = false;
StringBuilder builder = new StringBuilder();
int len = json.length();
for (int i = 0; i < len; i++) {
char c = json.charAt(i);
if (c == '\"')
quoted = !quoted;
if (quoted || !Character.isWhitespace(c))
builder.append(c);
}
return builder.toString();
}
同时,当使用时
Character.isWhitespace(c)
\"
!static String minimize(String input){
StringBuffer strBuffer = new StringBuffer();
boolean qouteOpened = false;
boolean wasEscaped = false;
for(int i=0; i<input.length(); i++){
char c = input.charAt(i);
if (c == '\\') {
wasEscaped = true;
}
if(c == '"') {
qouteOpened = wasEscaped ? qouteOpened : !qouteOpened;
}
if(!qouteOpened && (c == ' ')){
continue;
}
if (c != '\\') {
wasEscaped = false;
}
strBuffer.append(c);
}
return strBuffer.toString();
}
好的,这可能是我对这篇文章的最终回答:
public static CharSequence removeWhitespaces(CharSequence json) {
int len = json.length();
StringBuilder builder = new StringBuilder(len);
boolean escaped = false, quoted = false;
for (int i = 0; i < len; i++) {
char c = json.charAt(i);
if (c == '\"') {
if (!escaped) quoted = !quoted;
else escaped = false;
} else if (quoted && c == '\\') {
escaped = true;
}
if (quoted || c != ' ') {
builder.append(c);
}
}
return builder;
}
如果你想要确保去除所有的空格字符,那么可以使用如下代码:
public static CharSequence removeWhitespaces(CharSequence json) {
int len = json.length();
StringBuilder builder = new StringBuilder(len);
boolean escaped = false, quoted = false;
for (int i = 0; i < len; i++) {
char c = json.charAt(i);
if (c == '\"') {
if (!escaped) quoted = !quoted;
else escaped = false;
} else if (quoted && c == '\\') {
escaped = true;
}
if (quoted || !Character.isWhitespace(c)) {
builder.append(c);
}
}
return builder;
}
这种方法比先将字符串转换为Json结构,再转回字符串要高效得多,因为那样会非常耗时。
如果你有一个很长的输入字符串,提前告诉StringBuilder应该具有的起始容量也可以大大加快处理速度。 (容量不等于长度,这意味着即使你告诉StringBuilder它应该具有100的容量,它仍然只有你放入其中的文本长度)
由于StringBuilder实现了CharSequence,因此您可以直接返回整个StringBuilder,而无需将其转换回String。但是,如果您需要一个String而不是CharSequence,请在此方法的末尾调用builder.toString()并将返回类型设置为String。
jsonWriter.setIndent("");
去除 JSON 代码中的所有空格(已使用 Gson 的 Json Writer 进行测试)
{"a":1,"b":2}
等同于{"b":2,"a":1}
。 - Arfur Narf