【问题标题】:Get JSON.NET in WebAPI to serialize exact type not subclass在 WebAPI 中获取 JSON.NET 以序列化确切类型而不是子类
【发布时间】:2014-10-16 18:05:05
【问题描述】:

我在一个域中有三个类

public class ArtistInfo
{
    private Guid Id { get; set; }
    public string Name { get; set; }
    public string DisplayName { get; set; }
    public bool IsGroup { get; set; }
    public bool IsActive { get; set; }
    public string Country { get; set; }
}

public class Artist : ArtistInfo
{
    public DateTime Created { get; set; }
    public int CreatedById { get; set; }
    public DateTime Updated { get; set; }
    public int UpdatedById { get; set; }
}

public class Track
{
    public string Title { get; set; }
    public string DisplayTitle { get; set; }
    public int Year { get; set; }
    public int Duration { get; set; }
    public int? TrackNumber { get; set; }
    //[SomeJsonAttribute]
    public ArtistInfo Artist { get; set; }
}

从 ASP.NET Web API 我返回一个通用列表(曲目)。无论我尝试过什么,Web API 都会将 Track 的 Artist 属性返回为 Artist 而不是 ArtistInfo。有没有办法在 API 的输出中限制它只使用 ArtistInfo?我不想编写附加的“ViewModels/DTO”来处理这种情况。我可以用 JSON 序列化器的提示来装饰 ArtistInfo 吗?

【问题讨论】:

  • 使用的变量名“Artist”与类名“Artist”类似。你确定你没有误解 JSON 字符串吗?
  • 尝试在GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;中设置TypeNameHandling = TypeNameHandling.Auto;
  • 您可能需要使用自定义转换器:stackoverflow.com/q/5872855/497356

标签: c# serialization json.net asp.net-web-api


【解决方案1】:

获得所需结果的一种方法是使用自定义JsonConverter,它可以限制序列化的属性集。这是一个只会序列化基本类型T的属性的方法:

public class BaseTypeConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(T).IsAssignableFrom(objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JObject obj = new JObject();
        foreach (PropertyInfo prop in typeof(T).GetProperties())
        {
            if (prop.CanRead)
            {
                obj.Add(prop.Name, JToken.FromObject(prop.GetValue(value)));
            }
        }
        obj.WriteTo(writer);
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

要使用转换器,请在Track 类中使用[JsonConverter] 属性标记Artist 属性,如下所示。然后,只会序列化ArtistArtistInfo 属性。

public class Track
{
    public string Title { get; set; }
    public string DisplayTitle { get; set; }
    public int Year { get; set; }
    public int Duration { get; set; }
    public int? TrackNumber { get; set; }
    [JsonConverter(typeof(BaseTypeConverter<ArtistInfo>))]
    public ArtistInfo Artist { get; set; }
}

Demo here

【讨论】:

  • 非常感谢 dotnetfiddle 链接。我不知道它存在:)
【解决方案2】:

虽然布赖恩·罗杰斯的回答是恰当的。但是,如果您需要一个快速的解决方案,那么 [JsonIgnore] 属性会派上用场。

public class Artist : ArtistInfo
{
    [JsonIgnore]
    public DateTime Created { get; set; }
    [JsonIgnore]
    public int CreatedById { get; set; }
    [JsonIgnore]
    public DateTime Updated { get; set; }
    [JsonIgnore]
    public int UpdatedById { get; set; }
}

查看Demo Here。我已经更新了 Brian 的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多