FlySwat FlySwat - 5 months ago 75
JSON Question

DataContractJsonSerializer and Enums

When I serialize a enum value using DataContractJsonSerializer, it serializes the numerical value of the enum, not the string name.

IE:

enum foo
{
bar,
baz
}


Serializing a value of foo.bar returns "0", not "bar".

I'd prefer it the other way around, is there a way to override this?

Edit:

Because I didn't want to change the serializer, I used a simple workaround hack.

I exposed a property in the class to serialize that calls ToString on the value, ie:

// Old
[DataMember]
public EnumType Foo
{
get { return _foo; }
set { _foo = value; }
}

// New, I still kept the EnumType but I only serialize the string version

public EnumType Foo
{
get { return _foo; }
set { _foo = value; }
}

[DataMember]
public string FooType
{
get { return _foo.ToString(); }
private set {}
}

Answer

It looks like this is by design and this behavior cannot be changed:

Enumeration member values are treated as numbers in JSON, which is different from how they are treated in data contracts, where they are included as member names.

Here's an example using an alternative (and IMO better and more extensible) serializer which achieves what you are looking for:

using System;
using Newtonsoft.Json;

class Program
{
    static void Main(string[] args)
    {
        var baz = Foo.Baz;
        var serializer = new JsonSerializer();
        serializer.Converters.Add(new JsonEnumTypeConverter());
        serializer.Serialize(Console.Out, baz);
        Console.WriteLine();
    }
}

enum Foo
{
    Bar,
    Baz
}

public class JsonEnumTypeConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Foo);
    }
    public override void WriteJson(JsonWriter writer, object value)
    {
        writer.WriteValue(((Foo)value).ToString());
    }

    public override object ReadJson(JsonReader reader, Type objectType)
    {
        return Enum.Parse(typeof(Foo), reader.Value.ToString());
    }
}