Json.NET StringEnumConverter并不总是有效

时间:2015-01-28 07:50:33

标签: c# enums json.net

我有一个枚举:

public enum FilterOperator
    {
        [EnumMember(Value = "eq")]
        Equals,
        [EnumMember(Value = "gt")]
        GreaterThan,
        [EnumMember(Value = "lt")]
        LessThan,
        [EnumMember(Value = "in")]
        In,
        [EnumMember(Value = "like")]
        Like
    }

以及包含枚举属性的类:

public class GridFilter
{
    [JsonProperty("operator")]
    [JsonConverter(typeof(StringEnumConverter))]
    public FilterOperator Operator { get; set; }
}

通过WebAPI操作传入对象,并按照预期反序列化"类似"和" in"但它并不适用于" lg"或" gt"。知道为什么吗?

更新:原因"喜欢"和" in"工作是他们匹配枚举名称。将GreaterThan重命名为Gt(etc)可以正常工作。那么真正的问题是为什么没有使用StringEnumConverter?

3 个答案:

答案 0 :(得分:2)

感谢大家的帮助!我意识到我做了什么。可悲的是,这是相当愚蠢的,我道歉为此事而道歉。

由于我使用GET,我将参数作为url查询参数发送,因此WebAPI使用普通的ModelBinder来映射名称而不是JSON.NET。我实际上并没有发送JSON,所以这是完全有道理的。这个问题让我意识到这一点: Complex type is getting null in a ApiController parameter

我的选择是创建一个自定义模型绑定器,正确处理枚举或更改为POST并使用JSON.stringify()发送数据。

答案 1 :(得分:2)

好吧,如果要在外部反序列化时使用[JsonConverter(typeof(StringEnumConverter))]声明,则必须将enum属性直接放在Operator声明而不是GridFilter GridFilter属性上班级[JsonConverter(typeof(StringEnumConverter))] // Add this public enum FilterOperator { [EnumMember(Value = "eq")] Equals, [EnumMember(Value = "gt")] GreaterThan, [EnumMember(Value = "lt")] LessThan, [EnumMember(Value = "in")] In, [EnumMember(Value = "like")] Like } public class GridFilter { [JsonProperty("operator")] //[JsonConverter(typeof(StringEnumConverter")] // Remove this public FilterOperator Operator { get; set; } } 的上下文:

$('#form').attr('action', window.siteRoot + 'Users/Cards/').submit();

答案 2 :(得分:0)

这只是猜测,我还没有测试过。

我查看了EnumMemberAttribute的文档,并说:

  

要使用EnumMemberAttribute,请创建枚举并将DataContractAttribute属性应用于枚举。然后将EnumMemberAttribute属性应用于需要在序列化流中的每个成员。

那当然是DataContractSerializer,但我想也许JSON.net会考虑同样的规则?

我尝试将[DataContract]应用于enum

[DataContract]
public enum FilterOperator
{
    [EnumMember(Value = "eq")]
    Equals,
    [EnumMember(Value = "gt")]
    GreaterThan,
    [EnumMember(Value = "lt")]
    LessThan,
    [EnumMember(Value = "in")]
    In,
    [EnumMember(Value = "like")]
    Like
}

似乎是武断的,多余的。而且我知道JSON.net通常 依赖于那种东西,但也许在这种情况下呢?

我还注意到DataContractSerializer如果[EnumMember]存在,[DataContract]忽略没有EnumMemberAttribute的元素,那么它可能必须采用这种方式才能向后兼容。再次,不是超级逻辑。但这就是我所拥有的一切。


编辑以真正的开发人员方式,而不仅仅是测试,我进入了源代码。可以在第55行找到n2 = f.GetCustomAttributes(typeof(EnumMemberAttribute), true) .Cast<EnumMemberAttribute>() .Select(a => a.Value) .SingleOrDefault() ?? f.Name; 的{​​{1}}部分,并执行此操作:

public enum FilterOperator
{
    [EnumMember(Value = "eq")]
    Equals,
    [EnumMember(Value = "gt")]
    GreaterThan,
    [EnumMember(Value = "lt")]
    LessThan,
    [EnumMember(Value = "in")]
    In,
    [EnumMember(Value = "like")]
    Like
}
public class GridFilter
{
    [JsonProperty("operator")]
    [JsonConverter(typeof(StringEnumConverter))]
    public FilterOperator Operator { get; set; }
}


[TestMethod]
public void enumTest()
{
    GridFilter gf = new GridFilter()
    {
        Operator = FilterOperator.GreaterThan
    };

    var json = JsonConvert.SerializeObject(gf);

    // json yields {"operator":"gt"}

    var ret = JsonConvert.DeserializeObject<GridFilter>(json);
    // ret.Operator yields FilterOperator.GreaterThan
}

这让我觉得你所拥有的应该是有效的。


编辑2:

好吧,所以这很奇怪。我自己尝试过,发现它有效。

{{1}}