Reputation: 450
Let's say I have a JSON document that looks like this:
{
"Id" : "233124",
"RequestDate" : "2019-11-25T10:00:00"
"RequestPayload" : {
"Id" : "123abc",
"Url" : "http://blah.example/api/action",
"PostData" : "insert random post data here"
}
}
And I have a couple of C# POCOs that look like this:
public class RequestLog {
public string Id { get; set; }
public DateTime RequestDate { get; set; }
public object RequestPayload { get; set; }
}
public class RequestPayload {
public string Id { get; set; }
public string Url { get; set; }
public string PostData { get; set; }
}
Is there a way to have Json.Net deserialize the document such that the RequestLog.RequestPayload
property is of type RequestPayload
, even though it is declared as object
? The goal would be to cast it back to RequestPayload
in order to manipulate it, like this:
var result = JsonConvert.DeserializeObject<RequestLog>(json, ...);
var requestPayload = (RequestPayload)request.RequestPayload;
// do other stuff with requestPayload here
I can't change the declaration of RequestLog
, as it is in a NuGet package I don't control. I looked into creating a custom converter, and it seems like it should be possible, but I am utterly stumped as to how to pull it off.
Upvotes: 0
Views: 615
Reputation: 3164
If you must declare this RequestPayload
property of the RequestLog
as an object
, and you don't need this code to be reusable, you can brute force this.
JContainer json = GetMySerializedContentAsJson(content);
RequestPayload payload = JsonConvert.DeserializeObject<RequestPayload>(json["RequestPayload"]);
RequestLog log = JsonConvert.DeserializeObject<RequestLog>(json);
log.RequestPayload = payload;//=>you should now have your object.
Upvotes: 1
Reputation: 20373
You can use a custom converter for your RequestLog
class:
public class RequestLogConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType == typeof(RequestLog);
public override bool CanWrite => false;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject = JObject.Load(reader);
// Start by running the default serialisation
var log = new RequestLog();
serializer.Populate(jObject.CreateReader(), log);
// Manually deserialize RequestPayload
log.RequestPayload = jObject["RequestPayload"].ToObject<RequestPayload>();
return log;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Which can be used as follows:
JsonConvert.DeserializeObject<RequestLog>(json, new JsonSerializerSettings
{
Converters = new JsonConverter[] { new RequestLogConverter() }
});
Upvotes: 3
Reputation: 2950
In your RequestLog
class,
Change:
public object RequestPayload { get; set; }
to:
public RequestPayload RequestPayload { get; set; }
And then you'll be able to use it after deserialization, without having to cast it:
var result = JsonConvert.DeserializeObject<RequestLog>(json, ...);
var requestPayload = result.RequestPayload;
// do other stuff with requestPayload here
Upvotes: 0