簡體   English   中英

Newtonsoft Json反序列化為特定類型

[英]Newtonsoft Json deserialization into specific types

我有一個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

還是我應該選擇完全不考慮的完全不同的方法? 你們可以在這方面讓我留下您的意見嗎? 提前致謝

使用Newtonsoft.Json,您可以通過非泛型DeserializeObject(string value, type type)反序列化為一個類型。

這意味着您可以使用Type屬性作為要反序列化的Type的提示。

  1. 反序列化為基本類型
  2. 獲取實際Action對象的類型名稱
  3. 獲取全名類型的類型
  4. 反序列化為派生的動作類型

請參見以下示例:

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。

編輯 :根據意見,應該能夠deserialise的(派生類)操作的列表 因此,我將以下示例附加到我的答案中,您可以在其中看到如何通過執行以下操作對操作列表進行反序列化:

  1. 反序列化為通用JArray
  2. 為在陣列中的每個項目確定Type的的Action
  3. 反序列化為特定的派生類型

轉換后,我還添加了一個循環,以顯示如何進一步處理轉換后的動作。

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

        }

    }
}

您可以將其反序列化為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":{ ... }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM