【问题标题】:JsonConvert.DeserializeObject function throws errors when parse the obsolete enum propertiesJsonConvert.DeserializeObject 函数在解析过时的枚举属性时抛出错误
【发布时间】:2018-08-13 11:55:55
【问题描述】:

我想将现有的 Enum 属性标记为已过时,并添加新的以实现相同的功能。因此,我的项目中有两个枚举(新的和标记为过时的)。

使用 jsonconvert.deserializeobject 函数序列化此枚举值时,仅在 Newtonsoft 11.0 以上版本中会引发以下错误。

InvalidOperationException: Enum name 'stringedit' already exists on enum 'EditingType'. Newtonsoft.Json.Utilities.EnumUtils.InitializeValuesAndNames(Type enumType) JsonSerializationException: Error converting value "boolean" to type 'Student.Models.EditingType'. Path 'columns[0].editType', line 1, position 3997. Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, object value, CultureInfo culture, JsonContract contract, Type targetType)

如果我的项目需要进行任何更改,或者是否有任何计划从序列化函数中解决这个新错误。

我已将以下代码块用于我过时的枚举属性序列化。

[DataContract]

public enum EditingType

{

    [Obsolete("String property has been deprecated. Use StringEdit property instead")]

    [EnumMember(Value = "stringedit")]

    String,

    [EnumMember(Value = "stringedit")]

    StringEdit

}

public class JsonPropertyAttribute : Attribute

{
    public JsonPropertyAttribute(string argName)
    {
        PropertyName = argName;
    }

    public string PropertyName { get; set; }
}

public class JsonConverterAttribute : Attribute
{
    public Type ConverterType
    {
        get; set;
    }
    public string ValueType
    {
        get; set;
    }
    public JsonConverterAttribute(Type type, string valueType)
    {
        this.ConverterType = type;
        this.ValueType = valueType;
    }
    public JsonConverterAttribute(Type type)
    {
        this.ConverterType = type;

    }

}

public abstract class Converter
{
    protected internal abstract IDictionary<string, object> BuildJsonDictionary(object value);

    public abstract string SerializeToJson(object inputObject);
}
public class StringEnumConverter : Converter
{
    protected internal override IDictionary<string, object> BuildJsonDictionary(object value)
    {

        IDictionary<string, object> jsonDictionary = new Dictionary<string, object>();
        Type objectType = value.GetType();

        FieldInfo member = objectType.GetField(value.ToString(), BindingFlags.Static | BindingFlags.Public);

        var attrList = member.GetCustomAttributes(typeof(EnumMemberAttribute), true);
        var enumMember = attrList.OfType<EnumMemberAttribute>().FirstOrDefault();

        string val = enumMember != null ? enumMember.Value : value.ToString();

        jsonDictionary.Add(value.GetType().Name, val);

        return jsonDictionary;
    }


    public override string SerializeToJson(object inputObject)
    {
        var attrList = inputObject.GetType().GetCustomAttributes(false);
        var listAttr = attrList.ToList();
        FlagsAttribute flagAttr = attrList.Count() != 0 ? (FlagsAttribute)listAttr.Find(item => item.GetType() == typeof(FlagsAttribute)) : null;
        bool flag = (flagAttr != null) ? true : false;
        if (flag)
        {
            int value = (int)inputObject;
            return value.ToString();
        }
        else
        {
            IDictionary<string, object> enumDictionary = BuildJsonDictionary(inputObject);
            object enumValue = enumDictionary.First().Value;
            string enumstring = "\"" + enumValue.ToString() + "\"";
            return enumstring;
        }
    }
}

[Serializable]
public class TestClass
{
    private EditingType _editingType = EditingType.StringEdit;

    [JsonProperty("editType")]
    [DefaultValue(EditingType.StringEdit)]
    [JsonConverter(typeof(StringEnumConverter))]
    public EditingType EditType
    {
        get { return _editingType; }
        set { _editingType = value; }
    }
}

下面的反序列化函数将在最新的NewtonSoft.json(从11.X版本开始)中抛出错误

public class HomeController : Controller
{
    public IActionResult Index()
    {
       // This function will throws the error
        JsonConvert.DeserializeObject("{\"editType\":\"string\"}", typeof(TestClass));
        return View();
    }
}

谢谢..

【问题讨论】:

标签: c# enums json.net deserialization obsolete


【解决方案1】:

我对此进行了调查,这是预期的行为。 Json.NET 现在总是关心 EnumMember 并且你有重复的值。

如果要自定义其序列化,请实现 JsonConverter。我不知道您要对示例中的转换类做什么,但 Json.NET 并不关心它们。

Quoting Json.NET's author 来自@dbc 的 GitHub 链接

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 2018-07-24
    相关资源
    最近更新 更多