4

I have this sample converter for guid properties:

public class CustomGuidConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof (Guid?) || objectType == typeof (Guid);
    }

    public override void WriteJson(JsonWriter writer, object oldValue, JsonSerializer serializer)
    {
        if (value != null)
        {
            var newValue = convert(oldValue); // do some conversion
            writer.WriteValue(newValue);
        }
    }
}

using it like this:

public class Outer {
    public int Id { get; set; }

    [JsonConverter(typeof(InterfaceLabelConverter))]
    public Guid? ProductFamilyId { get; set; }
}

how can I access the name of the current property in the WriteJson method? I want to write the old value to writer with another propertyname like this:

{ Id: 1234, ProductFamilyId: 'newValue', ProductFamilyIdOld: 'oldValue' }
desolat
  • 4,123
  • 6
  • 36
  • 47
jansepke
  • 1,933
  • 2
  • 18
  • 30
  • Where is the old value coming from? – Andrew Whitaker May 21 '15 at 15:32
  • Is the 'oldGuid' the actual value that needs to be serialized and 'newGuid' the same value after conversion that you have mentioned in the question? – Ilija Dimov May 21 '15 at 16:48
  • What do you want the JSON for the outer object to look like? I.e. if the outer object is `public class Outer { public int Id { get; set; } public Guid? ProductFamilyId { get; set; } }`, then what JSON should be produced? – dbc May 21 '15 at 19:48

1 Answers1

5

I would recommend simply making the converted GUID be a private get-only property on the containing class. If you mark it with [JsonProperty] it will be serialized:

public class Outer
{
    public int Id { get; set; }

    public Guid? ProductFamilyId { get; set; }

    [JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
    Guid? OldProductFamilyId
    {
        get
        {
            return Convert(ProductFamilyId);
        }
    }

    private Guid? Convert(Guid? guid)
    {
        if (guid != null)
        {
            var bytes = guid.Value.ToByteArray();
            bytes[0] = unchecked((byte)~bytes[0]); // For example
            guid = new Guid(bytes);
        }
        return guid;
    }
}

That being said, you can pick the current property name off the JsonWriter.Path property:

public class InterfaceLabelConverter : JsonConverter
{
    private Guid? Convert(Guid? guid)
    {
        if (guid != null)
        {
            var bytes = guid.Value.ToByteArray();
            bytes[0] = unchecked((byte)~bytes[0]); // For example
            guid = new Guid(bytes);
        }
        return guid;
    }

    public override bool CanConvert(Type objectType)
    {
        throw new InvalidOperationException(); // This converter should only be applied directly to a property.
    }

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

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

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var path = writer.Path;
        var propertyName = path.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries).Last(); // Throw an exception if not found.
        if (propertyName.StartsWith("[") && propertyName.EndsWith("]"))
            throw new InvalidOperationException(); // Trying to use this converter for an array element.
        var guid = (Guid?)value;
        writer.WriteValue(guid);

        if (guid != null)
        {
            // Note -- actually the converter isn't called for null values, see
            // https://stackoverflow.com/questions/8833961/serializing-null-in-json-net
            var nextGuid = Convert(guid);
            var nextName = "Old" + propertyName;

            writer.WritePropertyName(nextName);
            writer.WriteValue(nextGuid);
        }
    }
}

And use it like:

public class Outer
{
    public int Id { get; set; }

    [JsonConverter(typeof(InterfaceLabelConverter))]
    public Guid? ProductFamilyId { get; set; }
}
dbc
  • 104,963
  • 20
  • 228
  • 340