简体   繁体   English

Newtonsoft Json反序列化为特定类型

[英]Newtonsoft Json deserialization into specific types

I have a class Action and many other specific classes that derive from this one like SendCoordinates, MakeCall, etc.. 我有一个Action类,以及从该类派生的许多其他特定类,例如SendCoordinates,MakeCall等。

So given a JSON response like this one: 因此,给出这样的JSON响应:

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

Now my question is regarding Newtonsoft json library. 现在我的问题是关于Newtonsoft json库。 What is the best way to implement this ? 实施此的最佳方法是什么? Should I create specific JSON converters for each class like they show here http://www.newtonsoft.com/json/help/html/DeserializeCustomCreationConverter.htm 我是否应该为每个类创建特定的JSON转换器,如它们在此处显示的http://www.newtonsoft.com/json/help/html/DeserializeCustomCreationConverter.htm

Or should I go for a entirelly different aproach that I'm not considering ? 还是我应该选择完全不考虑的完全不同的方法? Can you guys leave me your opinions on this ? 你们可以在这方面让我留下您的意见吗? Thanks in advance 提前致谢

With Newtonsoft.Json you can deserialise to a type via the non-generic overload DeserializeObject(string value, type type) . 使用Newtonsoft.Json,您可以通过非泛型DeserializeObject(string value, type type)反序列化为一个类型。

This means you can use the Type property as a hint to which type to deserialize. 这意味着您可以使用Type属性作为要反序列化的Type的提示。

  1. deserialise to base type 反序列化为基本类型
  2. get type name of actual Action object 获取实际Action对象的类型名称
  3. get type of type full name 获取全名类型的类型
  4. deserialise to derived action type 反序列化为派生的动作类型

See the following example: 请参见以下示例:

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);
        }

    }
}

If you do not want to specify the full qualified type name in the Type field, you can construct the FullName of the type by using custom programme logic (eg prefixing it with a base namespace). 如果您不想在“ Type字段中指定完整的限定类型名称,则可以使用自定义程序逻辑(例如,在基础名称空间的前面加上前缀)来构造类型的FullName。

Edit : according to the comments it should be able to deserialise a list of actions (of derived types). 编辑 :根据意见,应该能够deserialise的(派生类)操作的列表 Therefore I appended the following example to my answer where you can see, how to deserialise a list of actions by doing the following: 因此,我将以下示例附加到我的答案中,您可以在其中看到如何通过执行以下操作对操作列表进行反序列化:

  1. deserialise to generic JArray 反序列化为通用JArray
  2. for each item in array determine the Type of the Action 为在阵列中的每个项目确定Type的的Action
  3. deserialise into the specific derived type 反序列化为特定的派生类型

I also added a loop after the conversion to show how to further process the converted actions. 转换后,我还添加了一个循环,以显示如何进一步处理转换后的动作。

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;
                }
            }

        }

    }
}

You can deserialize it to SomeObject : 您可以将其反序列化为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 { ... }

Possible json to deserialize: 可能反序列化的json

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

or: 要么:

{
  "call":{ ... }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM