json作为常用数据文件,为了传输的效率,在传输前要进行压缩,而在传输后要进行格式化,以便阅读。下面是使用C#完成的格式化和压缩代码。
1 public static string Compress(string json) 2 { 3 StringBuilder sb = new StringBuilder(); 4 using (StringReader reader = new StringReader(json)) 5 { 6 int ch = -1; 7 int lastch = -1; 8 bool isQuoteStart = false; 9 while ((ch = reader.Read()) > -1) 10 { 11 if ((char)lastch != '\' && (char)ch == '"') 12 { 13 if (!isQuoteStart) 14 { 15 isQuoteStart = true; 16 } 17 else 18 { 19 isQuoteStart = false; 20 } 21 } 22 if (!Char.IsWhiteSpace((char)ch) || isQuoteStart) 23 { 24 sb.Append((char)ch); 25 } 26 lastch = ch; 27 } 28 } 29 return sb.ToString(); 30 }
因为在json中"是用作隔离key和value的,而"又可以作为value中的一部分,所以在处理中要判断是否是单独的",还是作为隔离符号,所以要进行如上的判断。
public static string Format(string json) { string strCompress = Compress(json); StringBuilder sb = new StringBuilder(); #region format using (StringReader reader = new StringReader(strCompress)) { using (StringWriter writer = new StringWriter(sb)) { int ch = -1; int lastch = -1; bool isQuoteStart = false; while ((ch = reader.Read()) > -1) { StringBuilder temp = new StringBuilder(); switch ((char)ch) { case '{': if (isQuoteStart) { temp.Append('{'); } else { temp.Append('{'); if ((char)reader.Peek() != '}') { temp.Append(Environment.NewLine); } } break; case '}': if (isQuoteStart) { temp.Append('}'); } else { if ((char)lastch != '{' && (char)lastch != '}') { temp.Append(Environment.NewLine); } temp.Append('}'); if ((char)reader.Peek() != ',') { temp.Append(Environment.NewLine); } } break; case '[': if (isQuoteStart) { temp.Append('['); } else { temp.Append('['); if ((char)reader.Peek() != ']') { temp.Append(Environment.NewLine); } } break; case ']': if (isQuoteStart) { temp.Append(']'); } else { if ((char)lastch != '[' && (char)lastch != ']') { temp.Append(Environment.NewLine); } temp.Append(']'); if ((char)reader.Peek() != ',' && (char)reader.Peek() != '}') { temp.Append(Environment.NewLine); } } break; case '"': if ((char)lastch != '\') { if (!isQuoteStart) { isQuoteStart = true; } else { isQuoteStart = false; } } temp.Append("""); break; case ':': if (isQuoteStart) { temp.Append(':'); } else { temp.Append(':'); temp.Append(" "); } break; case ',': if (isQuoteStart) { temp.Append(','); } else { temp.Append(','); temp.Append(Environment.NewLine); } break; case ' ': if (isQuoteStart) { temp.Append(" "); } else { temp.Append(""); temp.Append(Environment.NewLine); } break; default: temp.Append((char)ch); break; } writer.Write(temp.ToString()); lastch = ch; } } } #endregion format #region indent StringBuilder res = new StringBuilder(); using (StringReader reader = new StringReader(sb.ToString())) { using (StringWriter writer = new StringWriter(res)) { string str = null; int nspace = 0; string space = " "; bool bEndMid = false; while ((str = reader.ReadLine()) != null) { if (str.Length == 0) continue; if (str.EndsWith("},")) { nspace--; } StringBuilder temp = new StringBuilder(); if (!bEndMid) { for (int i = 0; i < (str.EndsWith("],") || (str.EndsWith("}") && !str.EndsWith("{}")) || str.EndsWith("]") ? nspace - 1 : nspace); i++) { temp.Append(space); } } temp.Append(str); if (str.EndsWith("[")) { writer.Write(temp); bEndMid = true; } else { writer.WriteLine(temp); bEndMid = false; } if (!(str.EndsWith("{}") || str.EndsWith("[]"))) { if (str.StartsWith("{") || str.EndsWith("{") || str.EndsWith("[")) { nspace++; } if (str.EndsWith("}") || str.EndsWith("]")) { nspace--; } } } } } return res.ToString(); #endregion indent }
对"的考虑同compress,但格式化的话需要考虑到缩进,而放到一起考虑比较麻烦,所以先进行了格式化,然后在处理缩进,这样就简化了逻辑。