C# 自定义序列化父项和嵌套项

C# 自定义序列化父项和嵌套项,c#,json,json.net,C#,Json,Json.net,我有一个例子,我想从JSON中删除一些多余项中的数据。(我不能只标记不使用Newtonsoft编写的项目,因为我需要它们用于另一个序列化调用。) 我正在使用自定义序列化程序来执行此操作,但它不会调用嵌套对象的序列化程序。或者可能接受JsonConverter数组的Serialized对象不是正确的调用 下面是一个完整的代码示例,其中从不调用CSerializer public class PItem { public string name = "Parent"; pub

我有一个例子,我想从JSON中删除一些多余项中的数据。(我不能只标记不使用Newtonsoft编写的项目,因为我需要它们用于另一个序列化调用。)

我正在使用自定义序列化程序来执行此操作,但它不会调用嵌套对象的序列化程序。或者可能接受JsonConverter数组的Serialized对象不是正确的调用

下面是一个完整的代码示例,其中从不调用CSerializer

  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
调用中将格式设置为缩进。