【问题标题】:Using WebApi in MVC4, how can I deserialize dynamic json to a concrete type?在 MVC 4 中使用 Web Api,如何将动态 json 反序列化为具体类型?
【发布时间】:2014-07-29 16:31:55
【问题描述】:

我正在尝试使用 MVC4 WebApi 来构建 rest/json 服务。

在我的控制器中,我有方法:

    public HttpResponseMessage Post(dynamic message)

这包含一个对象,它总是有两个字段,类型和操作。

操作是创建或取消。

我写了三个类,Message、CreateMessage和CancelMessage,Message是另外两个继承的基类。

在阅读了dynamic 上的简介后,我想我可以做到这一点:

    public void ProcessMessage(dynamic message)
    {
        switch ((string)message.action)
        {
            case "CREATE":
                ProcessCreateMessage(message);
                break;
            case "CANCEL":
                ProcessCancelMessage(message);
                break;
        }
    }

    private void ProcessCancelMessage(CancelMessage message)
    {
          //Cancell
    }

    private void ProcessCreateMessage(CreateMessage message)
    {
        //Create
    }

但我只是收到一条关于没有重载(隐式强制转换)或“无法将类型 'Newtonsoft.Json.Linq.JObject' 转换为 'CancelMessage'”的消息

public class Message
{
    public string type { get; set; }
    public string action { get; set; }
}

public class CancelMessage : Message
{
    public string ref { get; set; }
    public string message { get; set; }
}

Json:

{
    "type" : "type",
    "action" : "cancel",
    "ref" : "RefNo",
    "message" : "a message"
}

我在这里没有得到什么?

【问题讨论】:

    标签: c# asp.net-mvc json asp.net-mvc-4 asp.net-web-api


    【解决方案1】:

    您可以将 JSON 反序列化为 c# 对象,例如

    var cancelMessage = new JavaScriptSerializer().Deserialize<CancelMessage>(message);
    

    我认为默认情况下您不能将字符串(JSON)转换为对象。

    【讨论】:

    • 同样的问题,反序列化只需要一个字符串
    • 尝试将“消息”转换为字符串。
    【解决方案2】:

    请仔细阅读 Arcrain 的回答。

    Deserializing JSON to .NET object using Newtonsoft (or LINQ to JSON maybe?)

    我认为在你的情况下,它会从同一个 url 链接帮助你。

    You can use the C# dynamic type to make things easier. This technique also makes re-factoring simpler as it does not rely on magic-strings.
    
    Json
    
    The json string below is a simple response from an http api call and it defines two properties: Id and Name.
    
    {"Id": 1, "Name": "biofractal"}
    
    C#
    
    Use JsonConvert.DeserializeObject<dynamic>() to deserialize this string into a dynamic type then simply access its properties in the usual way.
    
    var results = JsonConvert.DeserializeObject<dynamic>(json);
    var id = results.Id;
    var name= results.Name;
    
    Note: The NuGet link for the NewtonSoft assembly is http://nuget.org/packages/newtonsoft.json
    

    希望它能解决您的问题。

    【讨论】:

    • 虽然我没有 Json,但我已经有一个动态对象。我试过var cancelMessage = JsonConvert.DeserializeObject&lt;CancelMessage&gt;(message);,我只是得到一个运行时错误,说反序列化需要一个字符串。
    • @RoboJ1M 尝试 JsonConvert.DeserializeObject(message);
    • 我知道了,var createMessage = JsonConvert.DeserializeObject&lt;CreateMessage&gt;(message.ToString()); 其中 message 是一个 JObject。 JObject 的 ToString() 重载返回底层 Json 字符串
    • 好的,很好的尝试..干得好...谢谢我以后也会关心它。
    【解决方案3】:

    这是另一个解决方案,使用 Janty 和 Babinicz 发布的信息

    像我一样在 MVC 4 中使用 ApiController,如果您将 dynamic 声明为您的单个传入参数。

    (我正在关注微软 MVC4 中的 Web Api 初学者指南)

    当您尝试将 dynamic 强制转换为某个东西时,它应该可以神奇地工作,但我遇到了一个错误。

    尝试编写自定义转换运算符,但您不能对动态执行此操作或从动态执行此操作

    但看起来dynamic 很像object,因为它知道它的底层类型是什么,并且该类型是 Newtonsoft 的 JObject

    dynamic 之间的转换只是进行正常转换,在运行时而不是设计时编译。

    因此,通过向模型类添加隐式转换运算符:

    public class Message
    {
        public string type { get; set; }
        public string action { get; set; }
    }
    
    public class CancelMessage : Message
    {
        public string ref { get; set; }
        public string message { get; set; }
    
        public static implicit operator CancelMessage(JObject message)
        {
            var output = JsonConvert.DeserializeObject<CancelMessage>(message.ToString());            
            return output;
        }
    }
    
    public void ProcessMessage(dynamic message)
    {
        switch ((string)message.action)
        {
            case "CANCEL":
                ProcessCancelMessage(message);
                break;
        }
    }
    
    private void ProcessCancelMessage(CancelMessage message)
    {
          //Cancel
    }
    

    这行得通。

    当然,如果我只是传递 dynamic 的东西,我的代码也可以工作,只要 json 中的字段名称符合预期。

    【讨论】:

      猜你喜欢
      • 2023-03-28
      • 1970-01-01
      • 2012-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-15
      相关资源
      最近更新 更多