如何将 Newtonsoft.Json.Linq.JObject 转换为复杂类型?

How to cast Newtonsoft.Json.Linq.JObject to complex type?

给定以下 C# 代码:

using Newtonsoft.Json;
using System;

namespace ConsoleApp2
{
    internal class Program
    {
        public class BatteryStatus
        {
            // The battery level reports percentage of the full battery.The field can take values from 0 to 100% (0x00 – 0x64).
            // The value 0xFF indicates a battery low warning.
            public byte BatteryLevel { get; set; }

            public bool LowBatteryWarning { get; set; }

            public DateTime TimestampUtc { get; set; }

            public BatteryStatus(byte batteryLevel)
            {
                TimestampUtc = DateTime.UtcNow;
                if (batteryLevel == 0xff)
                {
                    LowBatteryWarning = true;
                    batteryLevel = 0;
                }
                BatteryLevel = batteryLevel;
            }
        }

        static void Main(string[] args)
        {
            BatteryStatus batteryStatus = new BatteryStatus(40);
            string json = SaveObjectToJsonString(batteryStatus);
            Object obj = ReadObjectFromJsonString(json);
        }

        static string SaveObjectToJsonString(Object obj)
        {
            string json = JsonConvert.SerializeObject(obj);
            return json;
        }

        static Object ReadObjectFromJsonString(string json)
        {
            var obj = JsonConvert.DeserializeObject(json);
            return obj;
        }

    }
}

如果不更改 SaveObjectToString 或 ReadObjectFromString 函数(并假装您甚至没有看到这些函数的源代码),如何将 obj 转换为 BatteryStatus class 的对象?

正在尝试像这样直接投射:

batteryStatus = (BatteryStatus)obj;

导致以下错误:

无法将类型 'Newtonsoft.Json.Linq.JObject' 的对象转换为类型 'BatteryStatus'。

使用泛型的东西是否适合您的用例?

我们可以更改您的 ReadObjectFromJsonString 和 SaveObjectToJsonString 以使用泛型...

static string SaveObjectToJsonString<T>(Object obj) where T: class
        {
            string json = JsonConvert.SerializeObject(obj);
            return json;
        }

        static T ReadObjectFromJsonString<T>(string json) where T: class
        {
            var obj = JsonConvert.DeserializeObject<T>(json);
            return obj;
        }

然后调用这些函数时可以指定class -

BatteryStatus status = new BatteryStatus(40);
                string str = SaveObjectToJsonString<BatteryStatus>(status);
                BatteryStatus readBack = ReadObjectFromJsonString<BatteryStatus>(str);

您可以使用JObject.ToObject方法。

static void Main(string[] args)
        {
            BatteryStatus batteryStatus = new BatteryStatus(40);
            string json = SaveObjectToJsonString(batteryStatus);
            var obj = ReadObjectFromJsonString(json);
            JObject jObj = obj is JObject ? (JObject)obj : JObject.FromObject(obj);
            var deserializedBatteryStatus = jObj.ToObject<BatteryStatus>();
        }

试试这个

BatteryStatus BatteryStatus = ((JObject)obj).ToObject<BatteryStatus>();

这是我结合其他答案(使用 JObject 和泛型)的信息最终得到的解决方案:

  1. 在原始 ReadObjectFromJsonString 函数周围添加通用包装函数:
    static T ReadObjectFromJsonString<T>(string json)
    {
        var obj = ReadObjectFromJsonString(json);
        if (obj == null)
            return default;
    
        JObject jObj = obj is JObject ? (JObject)obj : JObject.FromObject(obj);
        return jObj.ToObject<T>();
    }
  1. 那么主要代码就会变得相当干净、简单和合乎逻辑:
    static void Main(string[] args)
    {
        BatteryStatus batteryStatus = new BatteryStatus(40);
        string json = SaveObjectToJsonString(batteryStatus);
        batteryStatus = ReadObjectFromJsonString<BatteryStatus>(json);
    }