Newtonsoft Json反序列化为特定类型

时间:2017-03-11 14:23:56

标签: c# json json.net json-deserialization

我有一个Action类和许多其他特定的类,它们来自SendCoordinates,MakeCall等。

所以给出了像这样的JSON响应:

 {
      "action":{
          "type":"SendCoordinates",
          "data": "41°24'12.2 N 2°10'26.5"
       }
}

现在我的问题是关于Newtonsoft json库。实现这个的最佳方法是什么?我应该为每个类创建特定的JSON转换器,就像它们在此处显示http://www.newtonsoft.com/json/help/html/DeserializeCustomCreationConverter.htm

一样

或者我应该选择一个我不考虑的完全不同的方法?你能告诉我你对此的看法吗?提前致谢

2 个答案:

答案 0 :(得分:2)

使用Newtonsoft.Json,您可以通过非泛型重载DeserializeObject(string value, type type)反序列化为类型。

这意味着您可以使用Type属性作为要反序列化的类型的提示。

  1. 反序列化为基本类型
  2. 获取实际Action对象的类型名称
  3. 获取类型全名
  4. 反序列化为派生操作类型
  5. 请参阅以下示例:

    using System;
    using Newtonsoft.Json;
    
    namespace com.example.SO42736347
    {
        public class Action
        {
            public string Type { get; set; }
        }
    
        public class Action1 : Action
        {
            public string Data { get; set; }
        }
    
        public class Program
        {
    
            public const string ACTION1 = @"{
                ""Type"" : ""com.example.Json.Action1"",
                ""Data"" : ""41°24'12.2 N 2°10'26.5""
            }";
    
            public static void Main()
            {
                var action = JsonConvert.DeserializeObject<Action>(ACTION1);
    
                var type = Type.GetType(action.Type);
    
                var action1 = (Action1) JsonConvert.DeserializeObject(ACTION1, type);
            }
    
        }
    }
    

    如果您不想在Type字段中指定完全限定类型名称,则可以使用自定义程序逻辑构造该类型的FullName(例如,为其添加基本命名空间)。

    编辑:根据评论,它应该能够反序列化列表操作(衍生类型)。因此,我将以下示例添加到我的答案中,您可以通过执行以下操作查看如何反序列化操作列表:

    1. 反序列化为通用JArray
    2. 对于数组中的每个项目,确定Type
    3. Action
    4. 反序列化为特定的派生类型
    5. 我还在转换后添加了一个循环,以显示如何进一步处理转换后的操作。

      using System;
      using Newtonsoft.Json;
      using System.Collections.Generic; 
      using Newtonsoft.Json.Linq;
      
      namespace com.example.Json
      {
          public class Action
          {
              public string Type { get; set; }
          }
      
          public class Action1 : Action
          {
              public string Data { get; set; }
          }
      
          public class Action2 : Action
          {
              public string SomeProperty { get; set; }
          }
      
          public class Program
          {
      
              public const string ACTION1 = @"{
              ""Type"" : ""com.example.Json.Action1"",
                  ""Data"" : ""41°24'12.2 N 2°10'26.5""
              }";
      
              public const string ACTION2 = @"{
              ""Type"" : ""com.example.Json.Action2"",
                  ""SomeProperty"" : ""arbitrary-value""
              }";
      
              public const string ACTIONS =  
                  "[" + 
                  ACTION1 +
                  "," + 
                  ACTION2 +
                  "]" ;
      
              public static void Main()
              {
      
                  var actions = new List<Action>();
      
                  JArray jArray = JArray.Parse(ACTIONS);
                  foreach(var item in jArray)
                  {
                      var json = JsonConvert.SerializeObject(item);
                      var baseAction = JsonConvert.DeserializeObject<Action>(json);
                      var type = Type.GetType(baseAction.Type);
                      var action = (Action) JsonConvert.DeserializeObject(json, type);
                      actions.Add(action);
                  }
      
                  // now that we have converted all array items into specific derived action objects
                  // we can start processing them anyway we want
                  // keep in mind that you have to check the runtime type in order to find out what
                  // specific kind of action we have
      
                  // eg.
                  foreach(var action in actions)
                  {
                      switch(action.Type)
                      {
                          case "com.example.Json.Action1":
                              // do something
                              Console.WriteLine("found com.example.Json.Action1");
                              Console.WriteLine((action as Action1).Data);
                              break;
                          case "com.example.Json.Action2":
                              // do something
                              Console.WriteLine("found com.example.Json.Action2");
                              Console.WriteLine((action as Action2).SomeProperty);
                              break;
                          default:
                              // do something
                              Console.WriteLine("found something else");
                              break;
                      }
                  }
      
              }
      
          }
      }
      

答案 1 :(得分:0)

您可以将其反序列化为SomeObject

public class SomeObject
{
  public SomeAction Action { get; set; }
  public OtherAction Call { get; set; }
}
public class SomeAction
{
  public string Type { get; set; }
  public string Data { get; set; }
}
public class OtherAction { ... }

可能json反序列化:

{
  "action":{ "type":"SendCoordinates", "data": "41°24'12.2 N 2°10'26.5" }
}

或:

{
  "call":{ ... }
}