为了账号安全,请及时绑定邮箱和手机立即绑定

如何在序列化期间忽略我不拥有的子类的属性?

如何在序列化期间忽略我不拥有的子类的属性?

C#
一只名叫tom的猫 2022-12-04 13:14:54
我有一个类Tempo。我可以自由改变:public class Tempo{    public Period Period { get; set; }    public int Value { get; set; } // in fact int should be a T here if it matters.    // more properties here}Period是来自我无法更改的外部依赖项的类。public class Period{    public DateTime Start { get; set; }    public DateTime End { get; set; }    public int Count { get; set; }    public string Foo { get; set; }    // more properties here}Period是一个巨大的类,有很多我不想序列化的属性。所以对我来说没有甜蜜[JsonIgnore]。从Period我想只保留属性Start和End。我尝试使用 aDefaultContractResolver但没有成功:class TempoResolver : DefaultContractResolver{    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)    {        var props = base.CreateProperties(type, memberSerialization);        return props            .Where(p => p.PropertyName != "Period") // how to filter subclass?            .ToList();    }}我尝试使用 aJsonConverter但没有成功:public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer){    var jo = new JObject();    var type = value.GetType();    jo.Add("type", type.Name);    foreach (var prop in type.GetProperties().Where(x => x.CanRead))    {        object propVal = prop.GetValue(value, null);        if (propVal != null)        {            jo.Add(prop.Name,             JToken.FromObject(propVal, serializer));  // how to filter subclass?        }    }    jo.WriteTo(writer);}在这两种情况下,我都不确定如何过滤Period. 如何在序列化期间忽略我不拥有的子类的属性?
查看完整描述

3 回答

?
当年话下

TA贡献1890条经验 获得超9个赞

JsonConverter您可以为类创建强类型Period:


public class PeriodConverter : JsonConverter<Period>

{

    public override void WriteJson(JsonWriter writer, Period period, JsonSerializer serializer)

    {

        writer.WriteStartObject();

        writer.WritePropertyName(nameof(Period.Start));

        writer.WriteValue(period.Start);

        writer.WritePropertyName(nameof(Period.End));

        writer.WriteValue(period.End);

        writer.WriteEndObject();

    }


    public override Period ReadJson(JsonReader reader, Type objectType, Period existingValue, bool hasExistingValue,

        JsonSerializer serializer)

    {

        throw new NotSupportedException();

    }

}

用法:


var tempo = new Tempo

{

    Period = new Period

    {

        Start = DateTime.Now.AddDays(-1),

        End = DateTime.Now.AddHours(-1),

        Count = 42,

        Foo = "Foo"

    },

    Value = 42

};


var result = JsonConvert.SerializeObject(tempo, new PeriodConverter());

var regularJson = JsonConvert.SerializeObject(tempo);

regularJson将具有以下所有属性Period:


{"期间":{"开始":"2019-04-08T12:21:39.1525361+03:00","结束":"2019-04-09T11:21:39.1535328+03:00","计数": 42,“富”:“富”},“值”:42}


并且result只期望:


{"期间":{"开始":"2019-04-08T12:21:39.1525361+03:00","结束":"2019-04-09T11:21:39.1535328+03:00"},"值" :42}


更新


WriteJson可以使用匿名对象简化代码:


public override void WriteJson(JsonWriter writer, Period period, JsonSerializer serializer)

{

    var token = JToken.FromObject(new {Start = period.Start, End = period.End});

    token.WriteTo(writer);

}


查看完整回答
反对 回复 2022-12-04
?
慕斯王

TA贡献1864条经验 获得超2个赞

制作子类:


public class Periodic

{

    public DateTime Start { get; set; }

    public DateTime End { get; set; }

}

使用带有此代码的自定义转换器:


public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)

{

    Periodic periodic = (Periodic)value;

    JToken t = JToken.FromObject(periodic);

    t.WriteTo(writer);

}


查看完整回答
反对 回复 2022-12-04
?
斯蒂芬大帝

TA贡献1827条经验 获得超8个赞

一种解决方案是使用以下子集Period:


// your external dependency

public class Period

{

    public DateTime Start { get; set; }

    public DateTime End { get; set; }

    public int Count { get; set; }

    public string Foo { get; set; }

}


// your copycat with only the properties you really need

public class Periodic

{

    public DateTime Start { get; set; }

    public DateTime End { get; set; }

}


public class Tempo

{

    public Periodic Period { get; set; }

    public int Value { get; set; }

}


public static void Main()

{

    var period = new Period{Count = 1, Foo = "bar", Start = DateTime.Now, End = DateTime.Now.AddDays(1)};

    var tempo = new Tempo{Value = 1, Period = new Periodic {Start = period.Start, End = period.End} };


    Console.WriteLine(JsonConvert.SerializeObject(tempo));

}

您还可以使用像Automapper这样的库来处理外部类和模仿者之间的映射。对于两个属性,它可能有点矫枉过正。



查看完整回答
反对 回复 2022-12-04
  • 3 回答
  • 0 关注
  • 99 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信