C# 自定义序列化父项和嵌套项
我有一个例子,我想从JSON中删除一些多余项中的数据。(我不能只标记不使用Newtonsoft编写的项目,因为我需要它们用于另一个序列化调用。) 我正在使用自定义序列化程序来执行此操作,但它不会调用嵌套对象的序列化程序。或者可能接受JsonConverter数组的Serialized对象不是正确的调用 下面是一个完整的代码示例,其中从不调用CSerializerC# 自定义序列化父项和嵌套项,c#,json,json.net,C#,Json,Json.net,我有一个例子,我想从JSON中删除一些多余项中的数据。(我不能只标记不使用Newtonsoft编写的项目,因为我需要它们用于另一个序列化调用。) 我正在使用自定义序列化程序来执行此操作,但它不会调用嵌套对象的序列化程序。或者可能接受JsonConverter数组的Serialized对象不是正确的调用 下面是一个完整的代码示例,其中从不调用CSerializer public class PItem { public string name = "Parent"; pub
public class PItem
{
public string name = "Parent";
public CItem child = new CItem();
public string type = "P";
}
public class CItem
{
public string name = "Child";
public int prop = 100;
public string[] codes = { "122a", "123b" };
}
class PSerializer : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.Formatting = Formatting.Indented;
PItem p = value as PItem;
JObject jo = JObject.FromObject((PItem)value);
jo.Remove("type");
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(PItem);
}
}
class CSerializer : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.Formatting = Formatting.Indented;
JObject jo = JObject.FromObject((CItem)value);
jo.Remove("codes");
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(CItem);
}
}
class JSONTest
{
public string TestConvert()
{
PItem p = new PItem();
JsonConverter[] serializers = { new PSerializer(), new CSerializer() };
return JsonConvert.SerializeObject(p, serializers);
}
}
基于Jesse的解决方案编辑工作代码
class PSerializer : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
PItem p = value as PItem;
JObject jo = JObject.FromObject((PItem)value);
var itemProperties = typeof(PItem).GetProperties(System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.DeclaredOnly);
var excludeList = new List<string> { "type" };
var itemProps = jo.Properties().Where(x => itemProperties.Any(y => y.Name == x.Name) && !excludeList.Any(y => y == x.Name));
writer.WriteStartObject();
foreach(var itemP in itemProps)
{
writer.WritePropertyName(itemP.Name);
serializer.Serialize(writer, itemP.Value);
}
writer.WriteEndObject();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(PItem);
}
}
class CSerializer : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.Formatting = Formatting.Indented;
//May cause performance issues but easy to write.
JObject jo = JObject.FromObject((CItem)value);
jo.Remove("codes");
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(CItem);
}
}
类PSerializer:JsonConverter
{
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
PItem p=作为PItem的值;
JObject jo=JObject.FromObject((PItem)值);
var itemProperties=typeof(PItem).GetProperties(System.Reflection.BindingFlags.Public
|System.Reflection.BindingFlags.Instance
|System.Reflection.BindingFlags.DeclaredOnly);
var excludeList=新列表{“类型”};
var itemProps=jo.Properties()。其中(x=>itemProperties.Any(y=>y.Name==x.Name)和&!excludeList.Any(y=>y==x.Name));
writer.WriteStartObject();
foreach(itemProps中的var itemP)
{
writer.WritePropertyName(itemP.Name);
serializer.Serialize(writer,itemP.Value);
}
writer.WriteEndObject();
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
抛出新的NotImplementedException();
}
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType==typeof(PItem);
}
}
类序列化器:JsonConverter
{
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
writer.Formatting=格式化.缩进;
//可能会导致性能问题,但易于编写。
JObject jo=JObject.FromObject((CItem)值);
删除(“代码”);
写作工作(作家);
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
抛出新的NotImplementedException();
}
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType==typeof(CItem);
}
}
使用自定义的
IContractResolver
执行此操作可能更容易:
public class IgnoreTypeContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.DeclaringType == typeof(PItem) && property.PropertyName == "type")
{
property.ShouldSerialize = i => false;
property.Ignored = true;
}
return property;
}
}
用法:
var settings = new JsonSerializerSettings();
settings.ContractResolver = new IgnoreTypeContractResolver();
var json = JsonConvert.SerializeObject(pitem, settings);
编辑:如果确实要使用JsonConverter
,则必须自己编写PItem对象,并使用JsonSerializer序列化子项:
// Inside your custom JsonConverter
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var pitem = value as PItem;
writer.WriteStartObject();
writer.WritePropertyName("name");
serializer.Serialize(writer, pitem.name);
writer.WritePropertyName("child");
// This respects any additional JsonConverters added to the serializer
serializer.Serialize(writer, pitem.child);
writer.WriteEndObject();
}
我已经有了父对象的序列化程序,它需要做的不仅仅是删除一些项,它还需要重新构造一些东西。嵌套对象只需删除内容。是否没有办法做到这一点,JSONConvert的数组是用于什么的?是的,有一种方法可以做到这一点,但您必须使用JsonWriter在JsonConverter中单独写入PItem的属性名称,然后调用serializer.Serialize对值进行序列化。这样,就可以在子项上使用自定义jsonconverter。我试图在这里避免这种情况,因为这相当拖沓。请参阅我对答案的编辑,以反映最新的评论。所以我有点喜欢这种解决方案,但这是一种痛苦。因为现在我也必须显式地写从孩子开始的所有内容,因为我不能做jo.WriteTo(writer),因为它处于“WrtieStartObject”模式,如果我结束它,我会得到一个全新的对象。应该有一种嵌套对象自动调用其序列化程序的方法。嗯,我不明白为什么子对象不可能这样。您可能忘记先写属性名了吗?请注意,您不想在
JsonConverter
中设置缩进格式。在JsonConvert.SerializeObject
调用中将格式设置为缩进。