简体   繁体   中英

How can you make a flags enum serialize its combination values numerically in C#?

Suppose you have a flags enum in C#:

[Flags]
public enum FlagsEnum
{
    One = 0x1,
    Two = 0x2,
    Four = 0x4,
    ...
}

If you run this through standard JSON or XML serialization, FlagsEnum.One will be serialized as the string One , FlagsEnum.Two as Two , etc. If you wanted to change it to have the values serialized as the integers 1 , 2 , etc., a typical solution for enums in general is to use the EnumMember attribute or XmlEnum attribute.

The problem is that with a flags enum, you're expecting several numerical values to be used that aren't specifically declared. Googling around doesn't seem to turn up much a solution for that scenario. So how would you get something like this to be serialized to integer values that aren't simply powers of 2, showing things in the serialized form like 23 , 15 , etc.?

EDIT

Part of what I'm looking for is a way to specify this within the enum itself, without adding any extra values to the enum or properties to other types. There is a question in my mind, however, whether that is actually possible (basically speaking).

Also the main type of serializer that this is really coming up with at the moment is DataContractSerializer . However typical, standard JSON stuff would also be applicable to this question, and the goal is to avoid changing out the serializers themselves and using anything customer or off the beaten path. (Attributes and stuff would be good, if it can be done that way.)

Serialization out of the box allows to save and restore flaged enum values:

<foo>Two Four</foo>

but with string values in XML

To save it as int interpretation you can make an int property and serialize it instead

[XmlIgnore]
public FlagsEnum foo{get;set;}
public int bar
{
    get{ return (int)foo;}
    set{ foo = (FlagsEnum)value;}
}

In that case your XML will have int values and the object will have full enum data

for DataContractSerializer and XmlSerializer works an option with IXmlSerializable interface implementation, but it's a bit too excess for a big classes

public void ReadXml(XmlReader reader)
{
    while (reader.Read())
    {
        if (reader.Name == "foo")
        {
            foo = (FlagsEnum)reader.ReadElementContentAsInt();
        }
    }
}

public void WriteXml(XmlWriter writer)
{
    writer.WriteElementString("foo", ((int)foo).ToString());
}

The simplest way would be just creating a separate int property for serialization.

public class DTO
{
    [JsonIgnore]
    public FlagsEnum Prop1 { get; set; }

    public int Prop1Serialize { 
       get { return (int)Prop1; }
       set { Prop1 = (FlagsEnum)value; }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM