Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I get the attributes on a property from the WriteJson method of a custom JsonConverter?

I want to decorate my classes with custom attributes, and read them when I convert to json using json.net inside a custom JsonConverter. I'll then vary the serialization depending on this custom attribute.

public class MyCustomJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        //I want to get any attributes set on the property here.
    }

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

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Int64);
    }
}

Another approach would be to specify my custom JsonConverter on the property using an attribute, but I don't want to do this because I want to inject some behaviour into the constructor of my custom JsonConverter by instantiating the converters in the JsonSerializer settings as below.

String json = JsonConvert.SerializeObject(new MyCLass(), new JsonSerializerSettings { Converters = new List { new MyCustomJsonConverter() } });

I can get to the name of the property in the textWriter path. And I can see some interesting hints in the documentation about Metadata, but I can't find a way to do this.

Here's an example decorated class:

public class MyCustomAttribute : Attribute { }
public class MyCLass
{
    [MyCustom]
    public Int64 MyInt { get; set; }
}
like image 902
Daniel James Bryars Avatar asked May 08 '14 21:05

Daniel James Bryars


1 Answers

JsonConverters apply to types, not to fields or properties.

Instead of adding an attribute to a property that uses an existing type, consider creating a new type and writing a convert for that instead.

public struct MyCustomType
{
    ...
}

public class MyClass
{
    public MyCustomType {get; set;}
}

Besides - in what other way would you ever want to serialize a raw integer? If the integer represents something, then create a struct or class for that something.

See also: "ValueObject" (Domain Driven Design fundamental concept)

Based on your comment below, an alternate approach would be to forget about JsonConverters and simply expose a secondary property:

public class MyClass
{
    [JsonIgnore]
    public Int64 MyInt {get; set;}

    [JsonProperty("MyInt")]
    public Int64 MyEncryptedInt
    {
        get { return Encrypt(MyInt); }
        set { MyInt = Decrypt(value); }
    }
}
like image 196
Matt Johnson-Pint Avatar answered Dec 04 '22 04:12

Matt Johnson-Pint