WebApi - 反序列化和序列化备用属性名称

11
我正在尝试找出如何在ASP.NET WebApi中指定替代属性名称,并使其适用于反序列化和序列化以及JSON和XML。目前我只发现了部分解决方案。我希望将属性名称公开为小写,带有下划线,并且(仅以示例为例)具有不同的内部名称:
外部:
- field-one - field-two
内部:
- ItemOne - ItemTwo
为测试,这里是一个POST控制器操作,只转发它接收到的内容:
// POST api/values
public TestSerialization Post([FromBody]TestSerialization value)
{
    return value;
}

还有一个测试实体:

public class TestSerialization
{
    [DataMember(Name = "field_one")] // Doesn't appear to change anything
    public string ItemOne { get; set; }

    [JsonProperty(PropertyName = "field_two")] // Only works for serialization in JSON mode
    public string ItemTwo { get; set; }
}

目前,我已经发现:

  • [DataMember(Name = "x")] 对序列化方向都没有影响。
  • [JsonProperty(Name = "x")] 当使用JSON时(它是JSON.NET属性,默认的序列化器),对序列化(返回值)有效。

为了测试数据,我提交了4个属性,以查看哪个值被反序列化,并且在反序列化时属性名称是什么:

  • ItemOne = "Value A"
  • ItemTwo = "Value B"
  • field-one = "Correct 1"
  • field-two = "Correct 2"

我该如何实现这一点?

2个回答

16

您的一些发现/结论是不正确的... 您可以尝试以下方法:

这对于Web API的默认Xml和Json格式化程序以及序列化和反序列化都应该有效。

[DataContract]
public class TestSerialization
{
    [DataMember(Name = "field_one")]
    public string ItemOne { get; set; }

    [DataMember(Name = "field_two")]
    public string ItemTwo { get; set; }
}

以下内容仅适用于 Json 格式,并且适用于序列化和反序列化。

public class TestSerialization
{
    [JsonProperty(PropertyName = "field_one")]
    public string ItemOne { get; set; }

    [JsonProperty(PropertyName = "field_two")]
    public string ItemTwo { get; set; }
}

1
啊 - 在类上缺少[DataContract]属性的情况下,从服务器序列化的结果在JSON和XML中都是正确的。来自UI的传入请求仍然只使用类的自然属性名称进行反序列化,而不是DataMember变量。 - Overflew
那不应该出现...你可以分享一下原始请求的样子吗? - Kiran
1
啊——我一直在使用Postman创建请求,并且在“x-www-form-encoded”选项卡中使用了手动输入的JSON数据。在“原始数据”选项卡中手动输入JSON数据可以得到预期的结果。我有点傻,但是对于一个“Rest API测试工具”,为什么第一和第二个选项卡(表单数据和表单URL编码)是玩意儿化的键/值编辑工具,而生成JSON请求的工具则需要手工操作让我有点困惑…… - Overflew
JsonProperty在问题的操作中无效,它总是被忽略。请描述您认为原帖作者的发现/结论有误的原因。 - Florian Winter

5
您可以通过将 JObject 传递给您的操作来强制 Asp.Net 使用 JSON 反序列化程序,尽管这样做有点麻烦。

然后,您可以将其视为 JObject 进行处理或调用 .ToObject<T>();,这将遵守 JsonProperty 属性。

// POST api/values
public IHttpActionResult Post(JObject content)
{
    var test = content.ToObject<TestSerialization>();
    // now you have your object with the properties filled correctly.
    return Ok();
}

1
我点赞了这个帖子,因为当我使用它时,我立即发现了为什么我的POCO无法被反序列化。抽象类失败。 - Nick Molyneux
对我来说不起作用。内容始终为“null”。 它可以与([FromBody]TestSerialization value)一起使用,但是JsonProperty被忽略了。 - Florian Winter
这对于发现使用内置模型绑定时的绑定错误非常有帮助。 - Michael K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接