C#中使用Newtonsoft.Json格式化输出
需求
- 如果属性内容为
-
则替换为null
- 如果属性内容为
""
则替换为null
- 如果一个节点下面的属性内容全部为
null
则将修改为[]
示例如下:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
public class TestClass
{
public string PropertyA { get; set; }
public string PropertyB { get; set; }
public NestedClass Nested { get; set; }
public List<NestedClass> Nesteds { get; set; }
}
public class NestedClass
{
public string NestedPropertyA { get; set; }
public string NestedPropertyB { get; set; }
}
public class CustomConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var obj = JObject.FromObject(value);
ProcessJToken(obj);
obj.WriteTo(writer);
}
private void ProcessJToken(JToken token)
{
if (token is JObject obj)
{
foreach (var property in obj.Properties().ToList())
{
ProcessJToken(property.Value);
if (property.Value.Type == JTokenType.String && (
property.Value.ToString() == "-" ||
property.Value.ToString() == ""))
{
property.Value.Replace(JValue.CreateNull());
}
}
if (obj.Properties().All(p => p.Value.Type == JTokenType.Null))
{
obj.RemoveAll();
}
}
else if (token is JArray arr)
{
foreach (var item in arr.ToList())
{
ProcessJToken(item);
}
if (arr.Children<JObject>().All(item => item.Properties().All(p => p.Value.Type == JTokenType.Null)))
{
arr.Replace(new JArray());
}
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var token = JToken.Load(reader);
ProcessJToken(token);
return token.ToObject(objectType);
}
public override bool CanConvert(Type objectType)
{
return true;
}
}
class Program
{
static void Main()
{
var json = @"{
""PropertyA"": ""-"",
""PropertyB"": """",
""Nested"": {
""NestedPropertyA"": ""-"",
""NestedPropertyB"": ""-""
},
""Nesteds"": [{
""NestedPropertyA"": ""-"",
""NestedPropertyB"": ""-""
}]
}";
var settings = new JsonSerializerSettings
{
Converters = { new CustomConverter() },
Formatting = Newtonsoft.Json.Formatting.Indented
};
var obj = JsonConvert.DeserializeObject<JObject>(json, settings);
var resultJson = JsonConvert.SerializeObject(obj, settings);
Console.WriteLine(resultJson);
}
}
结果如下所示:
1. 格式化输出前
{
"PropertyA": "-",
"PropertyB": "",
"Nested": {
"NestedPropertyA": "-",
"NestedPropertyB": "-"
},
"Nesteds": [
{
"NestedPropertyA": "-",
"NestedPropertyB": "-"
}
]
}
2. 格式化输出后
{
"PropertyA": null,
"PropertyB": null,
"Nested": {},
"Nesteds": []
}
C#使用typeof进行处理
1. 代码如下:
public static void RecursiveRemoveFormerName<T>(T t)
{
if (t == null) return;
if (t is List<FormerName> toRemove)
{
RemoveEmptyEntries(toRemove);
}
Type typeofT = t.GetType();
if (IsSimpleType(typeofT))
{
return;
}
else if (t is IEnumerable enumerable)
{
foreach (var item in enumerable)
{
RecursiveRemoveFormerName(item);
}
}
else
{
foreach (PropertyInfo prop in typeofT.GetProperties())
{
var obj = prop.GetValue(t);
RecursiveRemoveFormerName(prop.GetValue(t));
}
}
static bool IsSimpleType(Type type)
{
if (type.IsEnum)
return true;
TypeCode typeCode = Type.GetTypeCode(type);
switch (typeCode)
{
case TypeCode.Boolean:
case TypeCode.Byte:
case TypeCode.Char:
case TypeCode.DateTime:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.SByte:
case TypeCode.Single:
case TypeCode.String:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
return true;
default:
return false;
}
}
}
static void RemoveEmptyEntries(List<FormerName> toRemove)
{
for (int i = 0; i < toRemove.Count; ++i)
{
FormerName name = toRemove[i];
if (string.IsNullOrEmpty(name.EffectiveDate) && string.IsNullOrEmpty(name.Name))
{
toRemove.RemoveAt(i);
--i;
}
}
}