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 = "\t";
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,但格式化的话需要考虑到缩进,而放到一起考虑比较麻烦,所以先进行了格式化,然后在处理缩进,这样就简化了逻辑。