9

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; }
}
Daniel James Bryars
  • 4,429
  • 3
  • 39
  • 57
  • If you can get the name of the property, you also have obtained a PropertyInfo object of that property, right? Just use PropertyInfo.GetCustomAttributes(...) which will give you the custom attributes associated with the respective property... –  May 08 '14 at 22:04
  • Can you post an example of your class decorated with custom attributes? – Ilija Dimov May 08 '14 at 22:09
  • possible duplicate of [Reflection - get attribute name and value on property](http://stackoverflow.com/questions/6637679/reflection-get-attribute-name-and-value-on-property) –  May 08 '14 at 22:12
  • Elgonzo. Unfortunately not, I don't know of a way of getting the PropertyInfo - that would be great if I could. I only have the property name from the textWriter.Path. I don't have the Type or the name of the type either. – Daniel James Bryars May 08 '14 at 22:28
  • Lllija. Sure, I've added an example. I'm experimenting right now; I don't have a real example so I've made one up. – Daniel James Bryars May 08 '14 at 22:29
  • @DanielJamesBryars, but you have the object with the property being passed to WriteJson(...) as argument "value", right? Use "value.GetType()" to get the type object of *value*. –  May 08 '14 at 23:43

1 Answers1

3

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); }
    }
}
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Thanks, I will need to change all the other code I have to understand the new Value Type, but I think that's probably better. Why? Because sometimes for this specific Integer I want to encrypt it whilst it round trips the the client. – Daniel James Bryars May 10 '14 at 11:35
  • If it's simple encryption, you could consider an alternate approach, such as shown in my edit above. – Matt Johnson-Pint May 10 '14 at 19:56