'How to cast Newtonsoft.Json.Linq.JObject to complex type?
Given the following c# code:
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;
}
}
}
Without changing the SaveObjectToString or ReadObjectFromString functions (and pretend that you didn't even see the source code for these), how can obj be converted to an object of the BatteryStatus class?
Attempting to cast directly like this:
batteryStatus = (BatteryStatus)obj;
result in the following error:
Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'BatteryStatus'.
Solution 1:[1]
Would something using generics work for your use case?
We could change your ReadObjectFromJsonString and SaveObjectToJsonString to use generics...
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;
}
Then the class can be specified when you call those functions -
BatteryStatus status = new BatteryStatus(40);
string str = SaveObjectToJsonString<BatteryStatus>(status);
BatteryStatus readBack = ReadObjectFromJsonString<BatteryStatus>(str);
Solution 2:[2]
try this
BatteryStatus BatteryStatus = ((JObject)obj).ToObject<BatteryStatus>();
Solution 3:[3]
This is the solution I ended up with by combining information from the other answers (use of JObject and generics):
- Add a generic wrapper function around the original ReadObjectFromJsonString function:
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>();
}
- Then the main code will become quite clean, simple and logical:
static void Main(string[] args)
{
BatteryStatus batteryStatus = new BatteryStatus(40);
string json = SaveObjectToJsonString(batteryStatus);
batteryStatus = ReadObjectFromJsonString<BatteryStatus>(json);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Jeremy Farmer |
| Solution 2 | Serge |
| Solution 3 | OlavT |
