0

I want to locate my JsonSerializer settings in a separate file that forms a partial class along with the main class file. It is possible by using MetadataTypeAttribute:

[MetadataType(typeof(MyMeta))]
public partial class MainClass
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

internal sealed class MyMeta
{
    [JsonIgnore]
    public int ID { get; set; }

    [JsonProperty(PropertyName = "Title")]
    public string Name { get; set; }

    [JsonProperty(PropertyName = "Functions")]
    [JsonConverter(typeof(MyConverter))]
    public string Description { get; set; }
}

But what if it is not possible to append MetadataTypeAttribute to the MainClass? I tried to use the derived class in my Web API controller instead:

public partial class MainClass
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

[MetadataType(typeof(MyMeta))]
public partial class HelperClass : MainClass
{ }

public class TestController : ApiController
{
    public IEnumerable<HelperClass> Get()
    {
        var list = new List<HelperClass>()
        {
            new HelperClass() { ID = 0, Name = "Title 0", Description = "Description 0"},
            new HelperClass() { ID = 1, Name = "Title 1", Description = "Description 1"},
            new HelperClass() { ID = 2, Name = "Title 2", Description = "Description 2"}
        };
        return list;
    }
}

This trick works fine for validation attributes, but doesn't affect the TestController result. Why? What can I do to apply specific JsonSerializer settings to instances of MainClass without overriding/shadowing/encapsulation its public properties?

Alexander
  • 4,420
  • 7
  • 27
  • 42
  • Logic to check for `MetadataType` override attributes is built into [`JsonTypeReflector.GetAssociatedMetadataType()`](https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs#L269). There doesn't seem to be any way to inject an alternative to this static class into [`DefaultContractResolver`](https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs). – dbc Sep 08 '17 at 18:27
  • 1
    You may need to create a [custom `ContractResolver`](https://www.newtonsoft.com/json/help/html/contractresolver.htm#CustomIContractResolverExamples) that checks for override attributes and modifies the returned contract appropriately. – dbc Sep 08 '17 at 18:28
  • @dbc , thanks for your help! How can I register my custom ContractResolver in the infrastructure of my application? Or I need to send its instance to JsonSerializerSettings directly? – Alexander Sep 08 '17 at 19:16
  • *Or I need to send its instance to `JsonSerializerSettings` directly?* That's usually the correct way. You question doesn't specify your framework, but here are ways to do it for some of them: [Web API serialize properties starting from lowercase letter](https://stackoverflow.com/q/22130431); [Where should I plug in my custom DefaultContractResolver JSON.NET?](https://stackoverflow.com/q/24543385); [asp.net core 1.0 web api use camelcase](https://stackoverflow.com/q/38139607). – dbc Sep 08 '17 at 19:24
  • From the [docs](https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.metadatatypeattribute(v=vs.110).aspx#Examples) for `MetadataTypeAttribute`: *When you apply this attribute, you must adhere to the following usage constraints: The attribute cannot be inherited by derived classes; The attribute can be applied only one time.* So I don't think it's supposed to be possible for a derived class to override the metadata type of a base class. Rather, each level in the type hierarchy can have its own metadata, and Json.NET respects this. – dbc Sep 08 '17 at 20:04

0 Answers0