C# 修改JsonHelper
我很抱歉以这种方式问这个问题,但我显然没有足够的“声誉”在原始线程中将问题作为评论发布 有人制作了一个很好的小类来正确缩进JSON字符串,这样它更人性化。它工作得很好,只是我想修改它,使空数组由“[]”表示,而不是在字符之间有一堆空白(换行符,可能有几个缩进字符,等等)。这似乎是一个如此简单的计划 原始代码如下所示:C# 修改JsonHelper,c#,json,C#,Json,我很抱歉以这种方式问这个问题,但我显然没有足够的“声誉”在原始线程中将问题作为评论发布 有人制作了一个很好的小类来正确缩进JSON字符串,这样它更人性化。它工作得很好,只是我想修改它,使空数组由“[]”表示,而不是在字符之间有一堆空白(换行符,可能有几个缩进字符,等等)。这似乎是一个如此简单的计划 原始代码如下所示: private const string INDENT_STRING = " "; public static string FormatJson(strin
private const string INDENT_STRING = " ";
public static string FormatJson(string str)
{
var indent = 0;
var quoted = false;
var sb = new StringBuilder();
for (var i = 0; i < str.Length; i++)
{
var ch = str[i];
switch (ch)
{
case '{':
case '[':
sb.Append(ch);
if (!quoted)
{
sb.AppendLine();
Enumerable.Range(0, ++indent).ForEach(item => sb.Append(INDENT_STRING));
}
break;
case '}':
case ']':
if (!quoted)
{
sb.AppendLine();
Enumerable.Range(0, --indent).ForEach(item => sb.Append(INDENT_STRING));
}
sb.Append(ch);
break;
case '"':
sb.Append(ch);
bool escaped = false;
var index = i;
while (index > 0 && str[--index] == '\\')
escaped = !escaped;
if (!escaped)
quoted = !quoted;
break;
case ',':
sb.Append(ch);
if (!quoted)
{
sb.AppendLine();
Enumerable.Range(0, indent).ForEach(item => sb.Append(INDENT_STRING));
}
break;
case ':':
sb.Append(ch);
if (!quoted)
sb.Append(" ");
break;
default:
sb.Append(ch);
break;
}
}
return sb.ToString();
}
它让我大发雷霆,抱怨我引用了一个太大的索引(实际上,它抱怨了一些有很多可能性的东西,'ArgumentOutOfRangeException'
是最有可能的)。我试图添加一个跟踪器来查看str.Length是否为I+1>,但它仍然会爆炸。而它爆炸的地方在字符串的任何地方都不在[
或]
附近。实际上,ch
是一个“{”,而str[i+1]
是一个“,”
我说得通吗
我曾考虑过只使用结果字符串并使用正则表达式删除[and]之间的任何空格,但这似乎不雅观
是否有人建议如何修改这段优秀的代码,使之符合我的要求?我尝试过,真的尝试过…我使用了不同的方法。当我遇到方括号时,我会检查配对方括号的位置,并验证它之间不是空字符串。表达式如下:
isEmptyArray = nextMatchingBracketIndex != -1 ? stringRemainder.Substring(1, nextMatchingBracketIndex - 1).Trim().Length == 0 : false;
完整的工作代码为:
class JsonHelper
{
private const string INDENT_STRING = " ";
public static string FormatJson(string str)
{
var indent = 0;
var quoted = false;
var isEmptyArray = false;
var sb = new StringBuilder();
char ch = default(char);
for (var i = 0; i < str.Length; i++)
{
ch = str[i];
switch (ch)
{
case '{':
sb.Append(ch);
if (!quoted)
{
sb.AppendLine();
Enumerable.Range(0, ++indent).ForEach(item => sb.Append(INDENT_STRING));
}
break;
case '[':
sb.Append(ch);
var stringRemainder = str.Substring(i);
var nextMatchingBracketIndex = stringRemainder.IndexOf(']');
isEmptyArray = nextMatchingBracketIndex != -1 ? stringRemainder.Substring(1, nextMatchingBracketIndex - 1).Trim().Length == 0 : false;
if (!quoted && !isEmptyArray)
{
sb.AppendLine();
Enumerable.Range(0, ++indent).ForEach(item => sb.Append(INDENT_STRING));
}
break;
case '}':
if (!quoted)
{
sb.AppendLine();
Enumerable.Range(0, --indent).ForEach(item => sb.Append(INDENT_STRING));
}
sb.Append(ch);
break;
case ']':
if (!quoted && !isEmptyArray)
{
sb.AppendLine();
Enumerable.Range(0, --indent).ForEach(item => sb.Append(INDENT_STRING));
}
sb.Append(ch);
isEmptyArray = false;
break;
case '"':
sb.Append(ch);
bool escaped = false;
var index = i;
while (index > 0 && str[--index] == '\\')
escaped = !escaped;
if (!escaped)
quoted = !quoted;
break;
case ',':
sb.Append(ch);
if (!quoted)
{
sb.AppendLine();
Enumerable.Range(0, indent).ForEach(item => sb.Append(INDENT_STRING));
}
break;
case ':':
sb.Append(ch);
if (!quoted)
sb.Append(" ");
break;
default:
if (!isEmptyArray)
sb.Append(ch);
break;
}
}
return sb.ToString();
}
}
介于以下字符之间的空类型数组:
"types":[ ]
开头为空字符的完整类型数组
"types":[ "locality", "political"]
注意:在1,2,3中,我指的是链接中提供的原始JSON文件中的子字符串:
{"status":"OK", "results":[ {"types":[ "locality", "political"], "formatted_address":"New York, NY, USA", "address_components":[ {"long_name":"New York", "short_name":"New York", "types":[ "locality", "political"]}, {"long_name":"New York", "short_name":"New York", "types":[ "administrative_area_level_2", "political"]}, {"long_name":"New York", "short_name":"NY", "types":[ "administrative_area_level_1", "political"]}, {"long_name":"United States", "short_name":"US", "types":[ "country", "political"]}], "geometry":{"location":{"lat":40.7143528, "lng":-74.0059731}, "location_type":"APPROXIMATE", "viewport":{"southwest":{"lat":40.5788964, "lng":-74.2620919}, "northeast":{"lat":40.8495342, "lng":-73.7498543}}, "bounds":{"southwest":{"lat":40.4773990, "lng":-74.2590900}, "northeast":{"lat":40.9175770, "lng":-73.7002720}}}}]}
我已经用JSONLint测试了我在不同测试中得到的输出,它是有效的
我的时间是凌晨1点,我很确定我还没有涉及到一些边缘案例。但这段代码应该为您提供一种比现在更好的替代方法
"types":[ "locality", "political"]
{"status":"OK", "results":[ {"types":[ "locality", "political"], "formatted_address":"New York, NY, USA", "address_components":[ {"long_name":"New York", "short_name":"New York", "types":[ "locality", "political"]}, {"long_name":"New York", "short_name":"New York", "types":[ "administrative_area_level_2", "political"]}, {"long_name":"New York", "short_name":"NY", "types":[ "administrative_area_level_1", "political"]}, {"long_name":"United States", "short_name":"US", "types":[ "country", "political"]}], "geometry":{"location":{"lat":40.7143528, "lng":-74.0059731}, "location_type":"APPROXIMATE", "viewport":{"southwest":{"lat":40.5788964, "lng":-74.2620919}, "northeast":{"lat":40.8495342, "lng":-73.7498543}}, "bounds":{"southwest":{"lat":40.4773990, "lng":-74.2590900}, "northeast":{"lat":40.9175770, "lng":-73.7002720}}}}]}