简体   繁体   中英

c# Newtonsoft.json custom Enum serialization

I need to customize the way Newtonsoft.Json serializes an object, in particular about Enum types. Given a sample class like this:

    public class TestEnumClass
    {
        public Enum ReferencedEnum { get; set; }

        public string OtherProperty { get; set; }

        public StringSplitOptions OtherEnum { get; set; }
    }

The default serialization will happen this way:

var testEnumClass = new TestEnumClass
                            {
                                ReferencedEnum = StringComparison.OrdinalIgnoreCase,
                                OtherProperty = "Something",
                                OtherEnum = StringSplitOptions.None
                            };

var serialized = JsonConvert.SerializeObject(testEnumClass, Formatting.Indented);

And the serialized string will be:

{
  "ReferencedEnum": 5,
  "OtherProperty": "Something",
  "OtherEnum": 0
}

Here I have 2 problems:

  1. I cannot guarantee that the order of the Enums will remain the same (here I am using Enums included in the framework, but my project has other Enums that derive from ": Enum"), so I cannot keep the number as the serialized value of the Enum.
  2. Secondly, and more important, is the fact that the "ReferencedEnum" field is declared as "Enum", and any kind of Enum can be written in that field (ReferencedEnum = AnyEnum.AnyEnumValue). This leads to the fact that when deserializing the value, I need to know the original Enum type (in the example is StringComparison).

I was thinking of using a Converter (deriving from ": JsonConverter") and manipulating what is written and read. The result I was thinking was something like this:

{
  "ReferencedEnum": { 
    "EnumType": "StringComparison",
    "EnumValue": "OrdinalIgnoreCase"
  },
  "OtherProperty": "Something",
  "OtherEnum": "StringSplitOptions.None"
}

I this way the deserializer would know:

  1. for "Enum" properties, the original type and the string value.
  2. for "typed Enum" (specific enum) properties, the full type and value.

What I cannot absolutely add is a reference to the converter in the model class like this:

[JsonConverter(typeof(EnumConverter))]
public Enum ReferencedEnum { get; set; }

And I also would avoid to have the "$type" field in the serialized string (except if this is the only solution).

By the way, I can add a generic attribute like this:

[IsEnum]
public Enum ReferencedEnum { get; set; }

Does somebody have any idea of how can I get the result needed?

Thank you!

I've been in the very same issue and developed a nuget package named StringTypeEnumConverter , that solves it. You can check the project here . The usage will be as simple as any other converter.

This converter derives from an already existing "StringEnumConverter", that writes the string value of the enum, instead of its numeric counterpart. I added the support to writing the type name too.

The result will be like: "StringSplitOptions.None" (this is a string value, not an object).

Note that this converter should be applied for both writing and reading, as the resulting json would not be compatible with other readers not including this converter.

You should consider using this package only if you cannot avoid using enums in your model. I would also suggest you to spend time to check if (custom) enums could be transformed to classes.

J.

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