5

I have three classes in a domain

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; }
}

From the ASP.NET Web API I return a generic List(of Tracks). No matter what I have tried the Web API returns the Artist property of Track as an Artist not ArtistInfo. Is there someway to limit this in the output of the API to just use ArtistInfo? I don't want to write addition "ViewModels/DTOs" to handle this situation. Can I decorate the ArtistInfo with a hint to the JSON Serializer?

3
  • The used variable name "Artist" is similar to the class name "Artist". are you sure you are not misinterpreting the JSON string ? Commented Aug 22, 2014 at 20:04
  • Try setting TypeNameHandling = TypeNameHandling.Auto; in GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings; Commented Aug 22, 2014 at 20:14
  • You may have to use a custom converter: stackoverflow.com/q/5872855/497356 Commented Aug 22, 2014 at 22:18

2 Answers 2

1

One way to get the result you want is to use a custom JsonConverter that can limit the set of properties serialized. Here is one that will only serialize the properties of a base type 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();
    }
}

To use the converter, mark the Artist property in your Track class with a [JsonConverter] attribute as shown below. Then, only the ArtistInfo properties of the Artist will be serialized.

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

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a ton for dotnetfiddle link. I did not knew it exists :)
0

Although Answer by Brian Rogers has been appropriate one. But if you need a quick solution than [JsonIgnore] property would come handy.

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; }
}

Check out Demo Here. I have updated Brian's code.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.