Deserialize specific enum into system.enum in Json.Net

The difficulty here is that System.Enum is an abstract class, so it is impossible to deserialize a value of unknown concrete type as such a type. Rather, one needs to have the specific type information in the JSON somewhere, however Json.NET will serialize an enum as a string or an integer (depending upon whether a StringEnumConverter is applied) -- but not an as an object, thus leaving no opportunity for a polymorphic "$type" property to be added.

The solution is, when serializing, to serialize a generic wrapper class that can convey the concrete type information:

public abstract class TypeWrapper
{
    protected TypeWrapper() { }

    [JsonIgnore]
    public abstract object ObjectValue { get; }

    public static TypeWrapper CreateWrapper<T>(T value)
    {
        if (value == null)
            return new TypeWrapper<T>();
        var type = value.GetType();
        if (type == typeof(T))
            return new TypeWrapper<T>(value);
        // Return actual type of subclass
        return (TypeWrapper)Activator.CreateInstance(typeof(TypeWrapper<>).MakeGenericType(type), value);
    }
}

public sealed class TypeWrapper<T> : TypeWrapper
{
    public TypeWrapper() : base() { }

    public TypeWrapper(T value)
        : base()
    {
        this.Value = value;
    }

    public override object ObjectValue { get { return Value; } }

    public T Value { get; set; }
}

Then use serialize the wrapper when serializing your class:

    /// <summary>
    /// The enum flag associated with the rule, if applicable.  CAN be null.
    /// </summary>
    [JsonIgnore]
    public System.Enum RuleFlagEnum { get; set; }

    [JsonProperty("RuleFlagEnum", TypeNameHandling = TypeNameHandling.All)]
    TypeWrapper RuleFlagEnumValue
    {
        get
        {
            return RuleFlagEnum == null ? null : TypeWrapper.CreateWrapper(RuleFlagEnum);
        }
        set
        {
            if (value == null || value.ObjectValue == null)
                RuleFlagEnum = null;
            else
                RuleFlagEnum = (Enum)value.ObjectValue;
        }
    }

This produces JSON like the following:

{
  "RuleType": "ModifyDifficulty",
  "RuleFlagEnum": {
    "$type": "Question31351262.TypeWrapper`1[[Question31351262.MyEnum, MyApp]], MyApp",
    "Value": "Two, Three"
  },
}

Comments

  1. Roberts

    • 2019/4/17

    The difficulty here is that System.Enum is an abstract class, so it is impossible to deserialize a value of unknown concrete type as such a 

  2. Yehuda

    • 2018/6/10

    The difficulty here is that System.Enum is an abstract class, so it is impossible to deserialize a value of unknown concrete type as such a type. Rather, one needs to have the specific type information in the JSON somewhere, however Json.NET will serialize an enum as a string or an integer (depending upon whether a StringEnumConverter is applied) -- but not an as an object, thus leaving no

  3. Kelly

    • 2016/1/6

    Json.NET comes with the StringEnumConverter to convert between an enum Json.Converters; using NUnit.Framework; using System.Collections.

  4. Caspian

    • 2017/8/29

    Entity. Json.NET comes with the StringEnumConverter to convert between an enum and the JSON string representation. The property of the ErrorCode enum simply needs to be attributed as a JsonConverter of type StringEnumConverter in order to be serialized and deserialized. public class SampleEntity { [JsonProperty ("error")] [JsonConverter (typeof

  5. Jaime

    • 2017/10/1

    Then Json.NET is instructed to serialize/deserialize the enum value as a string with [JsonConverter(typeof(StringEnumConverter))] attribute.

  6. Joey

    • 2019/7/31

    In System.Text.Json in .Net Core 3.1, I can serialize an enum using a naming policy, however when I attempt to deserialize the same enum with a naming policy, the policy is ignored and an exception is thrown when the naming policy does anything beyond modifying the case of the enum value names.

  7. Ryder

    • 2019/10/31

    If you try to serialize an enum in .NET Core 3.0 with the default library, it will convert it into an integer value instead of the name of 

  8. Enoch

    • 2016/10/15

    Deserialize into a JSON DOM (document object model) and extract what you need from the DOM. The DOM lets you navigate to a subsection of a JSON payload and deserialize a single value, a custom type, or an array. For information about the JsonNode DOM in .NET 6, see Deserialize subsections of a JSON payload.

  9. Theodore

    • 2020/3/31

    NET page. Additionally, to have your enum member to serialize/deserialize to/from specific text, use the. System.Runtime.Serialization.EnumMember.

  10. Kai

    • 2019/1/12

    Just add: using System.Text.Json.Serialization;. Unfortunately, it seems Swagger (Swashbuckle.AspNetCore 5.0.0-rc3) is not ready yet to handle this properly as in the generated doc the enum types are marked as int even if they are properly serialized as strings.

  11. Cooper

    • 2017/5/6

    This is somewhat involved in general as it is necessary to handle parsing of integer and string values, renaming of each component of a [Flags] enum value, and 

  12. Castillo

    • 2018/2/1

    In Json.NET, dynamic properties are serialized and deserialized exactly the same as untyped objects: because dynamic isn't an actual type, Json.NET falls back to deserializing the JSON as LINQ to JSON objects. The second usage of dynamic in .NET are by the types that implement IDynamicMetaObjectProvider. This interface lets the implementer

  13. Jose

    • 2020/11/10

    Converts an Enum to and from its name string value. Inheritance Hierarchy. System.Object · Newtonsoft.Json.JsonConverter. Newtonsoft.Json.Converters.

  14. Zechariah

    • 2020/10/11

    Included members are written to JSON. Has no effect when deserializing. Ignore, 1, Ignore members where the member value is the same as the member's default 

  15. Hernandez

    • 2015/8/1

    In System.Text.Json in .Net Core 3.1, I can serialize an enum using a naming policy, however when I attempt to deserialize the same enum 

Comments are closed.

Recent Posts