下面我会详细讲解“C# 格式化JSON的两种实现方式”的完整攻略。
标准化JSON
在对JSON进行格式化处理之前,我们需要首先将其标准化,这样可以排除语义上的差异,从而方便后续的处理。具体实现方法是:按照字典序对JSON的对对象属性进行排序,这个排序过程会递归遍历对象及其属性。
在C#中,可以使用Newtonsoft.Json库提供的以下类和方法来将JSON进行标准化处理:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public static string NormalizeJson(string json)
{
JToken parsedJson = JToken.Parse(json);
JToken normalizedJson = NormalizeJsonRecursive(parsedJson);
return JsonConvert.SerializeObject(normalizedJson, Formatting.None);
}
private static JToken NormalizeJsonRecursive(JToken json)
{
if (json is JObject obj)
{
// Sort property names.
JProperty[] properties = obj.Properties().OrderBy(p => p.Name).ToArray();
// Recreate object with sorted properties.
obj = new JObject(properties.Select(p => new JProperty(p.Name, NormalizeJsonRecursive(p.Value))));
}
else if (json is JArray array)
{
// Recreate array with recursively normalized elements.
array = new JArray(array.Select(NormalizeJsonRecursive));
}
return json.DeepClone(); // Avoid modifying the original JSON.
}
上述代码中,NormalizeJson
方法将输入的JSON字符串进行解析,然后调用NormalizeJsonRecursive
方法对JSON进行标准化处理,并最终通过JsonConvert.SerializeObject
方法将标准化后的JSON序列化为字符串输出。
在NormalizeJsonRecursive
方法中,通过判断json
的类型,分别对对象和数组进行递归处理。对于对象,我们将其属性按照字典序进行排序,并重新创建一个对象;对于数组,我们递归处理其中的每一个元素,并重新创建一个数组。最后,由于C#中的对象和数组都是引用类型,因此需要使用DeepClone
方法来避免修改原始的JSON对象。
方法一:使用正则表达式
一种比较常见的JSON格式化方法是使用正则表达式。这种方法的思路是将JSON字符串中的所有{
、}
、[
、]
、,
以及:
前后添加换行符和缩进。
在C#中,实现此方法的代码如下:
private static string FormatJsonWithRegex(string json)
{
string pattern = @"([{,])(\s*)([\w\d_""]+?)\s*:";
string replacement = "$1\n$2$3: ";
string formattedJson = Regex.Replace(json, pattern, replacement, RegexOptions.Multiline);
pattern = @"(})([\],])";
replacement = "$1\n$2";
formattedJson = Regex.Replace(formattedJson, pattern, replacement, RegexOptions.Multiline);
return formattedJson;
}
上述代码分别定义了两个正则表达式,用于匹配需要添加换行符和缩进的位置。在第一个表达式中,$1
表示匹配到的{
、}
、[
、]
或,
;$2
表示该符号前的空格数量;$3
表示该符号后的属性名或数组元素。通过使用$1\n$2$3:
来替换,可以在符号前添加换行符和缩进。同理,在第二个表达式中,$1
表示匹配到的{
或}
;$2
表示该符号后的,
或]
,通过使用$1\n$2
来替换,可以在符号后添加换行符和缩进。
这种方法的优点是简单易懂,代码量较小,适用于格式化简单的JSON字符串。缺点是正则表达式可能比较难以维护,并且在处理复杂的JSON字符串时可能会出现问题。
例如,对于以下JSON字符串:
{
"name": "John",
"age": 30,
"cars": [
{ "name": "Ford", "models": ["Fiesta", "Focus", "Mustang"] },
{ "name": "BMW", "models": ["320", "X3", "X5"] },
{ "name": "Fiat", "models": ["500", "Panda", "Punto"] }
]
}
使用上述方法处理后的结果为:
{
"name": "John",
"age": 30,
"cars": [
{"name": "Ford", "models": ["Fiesta", "Focus", "Mustang"]},
{"name": "BMW", "models": ["320", "X3", "X5"]},
{"name": "Fiat", "models": ["500", "Panda", "Punto"]}
]
}
可以看出,该方法可以正确地格式化简单的JSON字符串。
方法二:使用JsonTextWriter
另一种JSON格式化方法是使用JsonTextWriter,该方法的基本思路是在读取JSON字符串的同时对其进行格式化处理。具体实现方法是递归遍历JSON中的每一个属性或元素,并根据其类型进行不同的处理,从而在输出JSON字符串时插入换行符和缩进。
由于这种方法需要递归遍历JSON对象,因此适用于格式化复杂的JSON字符串。在C#中,可以使用以下代码实现:
private static string FormatJsonWithJsonTextWriter(string json)
{
StringBuilder output = new StringBuilder();
StringWriter writer = new StringWriter(output);
using (JsonReader reader = new JsonTextReader(new StringReader(json)))
using (JsonTextWriter writerWrapper = new JsonTextWriter(writer) { Formatting = Formatting.Indented })
{
FormatJsonElement(reader, writerWrapper);
}
return output.ToString();
}
private static void FormatJsonElement(JsonReader reader, JsonTextWriter writer)
{
switch (reader.TokenType)
{
case JsonToken.StartObject:
writer.WriteStartObject();
while (reader.Read() && reader.TokenType != JsonToken.EndObject)
{
if (reader.TokenType == JsonToken.PropertyName)
{
writer.WritePropertyName(reader.Value.ToString());
FormatJsonElement(reader, writer);
}
}
writer.WriteEndObject();
break;
case JsonToken.StartArray:
writer.WriteStartArray();
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
FormatJsonElement(reader, writer);
}
writer.WriteEndArray();
break;
case JsonToken.String:
case JsonToken.Integer:
case JsonToken.Float:
case JsonToken.Boolean:
writer.WriteValue(reader.Value);
break;
case JsonToken.Null:
writer.WriteNull();
break;
}
}
在上述代码中,FormatJsonWithJsonTextWriter
方法首先创建一个StringBuilder对象和一个StringWriter对象,用于存储和输出格式化后的JSON字符串。然后使用JsonTextReader读取输入的JSON字符串,并将其转换为JsonTextWriter对象。
FormatJsonElement
方法实现了对JSON中每个元素的遍历处理,对于Object类型的元素,我们首先输出其开头的{
,然后遍历每个属性,对每个属性进行处理,并在末尾输出}
;对于Array类型的元素,我们输出[
,然后遍历每个元素,对每个元素进行处理,并在末尾输出]
;对于String、Integer、Float、Boolean和Null类型的元素,我们直接输出其值。在进行递归时,我们使用了JsonReader的Read方法来获取下一个元素,并在每一个分支中进行递归处理。
这种方法的优点是可以处理比较复杂的JSON字符串,并且不需要使用正则表达式,因此代码可维护性较高。缺点是需要递归遍历JSON对象,因此在处理大型JSON字符串时可能会影响性能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 格式化JSON的两种实现方式 - Python技术站