Search code examples
c#jsondatacontract

Serialize enum to string


I have an enum:

public enum Action {
    Remove=1,
    Add=2
}

And a class:

[DataContract]
public class Container {
    [DataMember]
    public Action Action {get; set;}
}

When serialize instance of Container to json I get: {Action:1} (in case Action is Remove).

I would like to get: {Action:Remove} (instead of int I need to ToString form of the enum)

Can I do it without adding another member to the class?


Solution

  • The JSON formatter has very specialized behaviour when working with enumerations; the normal Data Contract attributes are ignored and it treats your enum as a number, not the more human-readable string you'd expect with other formats. Whilst this makes it easy to deal with flag-type enumerations, it makes most other types much harder to work with.

    From MSDN:

    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. For more information about the data contract treatment, see Enumeration Types in Data Contracts.

    • For example, if you have public enum Color {red, green, blue, yellow, pink}, serializing yellow produces the number 3 and not the string "yellow".

    • All enum members are serializable. The EnumMemberAttribute and the NonSerializedAttribute attributes are ignored if used.

    • It is possible to deserialize a nonexistent enum value - for example, the value 87 can be deserialized into the previous Color enum even though there is no corresponding color name defined.

    • A flags enum is not special and is treated the same as any other enum.

    The only practical way to resolve this, to allow end-users to specify a string instead of a number, is to not use the enum in your contract. Instead the practical answer is to replace your enum with a string and perform internal validation on the value such that it can be parsed into one of the valid enum representations.

    Alternatively (though not for the feint of heart), you could replace the JSON formatter with your own, which would respect enumerations in the same way as other formatters.