Here is a solution using a custom JsonConverter and Newtonsoft.Json.
This will set SomeObject
to null in MyObject
if it is an array. You can return a new instance of SomeObject
instead by returning (T)Activator.CreateInstance(typeof(T))
.
public class ArrayToObjectConverter<T> : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Array)
{
// this returns null (default(SomeObject) in your case)
// if you want a new instance return (T)Activator.CreateInstance(typeof(T)) instead
return default(T);
}
return token.ToObject<T>();
}
public override bool CanConvert(Type objectType)
{
return true;
}
public override bool CanWrite
{
get { return true; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}
Note that Newtonsoft.Json ignores CanConvert
(since the property is decorated with JsonConverter
attribute) it assumes it can write and convert so does not call these methods (you could return false or throw NotImplementedException instead and it will still serialize/deserialize).
In your model, decorate some_object
with the JsonConvert
attribute. Your class might look something like this:
public class MyObject
{
[JsonProperty("some_object")]
[JsonConverter(typeof(ArrayToObjectConverter<SomeObject>))]
public SomeObject SomeObject { get; set; }
}
I know you said you'd prefer to use System.Text.Json but this might be useful for others using Json.Net.
Update: I did create a JsonConverter solution using System.Text.Json and it is here.
[OnError]
attributes. – NavarreJsonConvert.DeserializeObject<MyObject>("some json string", new JsonSerializerSettings { Error = MyDeserializationErrorHandler });
Newtonsoft Documentation – StongeJsonToken.StartArray
check for your property and then return null from there. #40439790 – Lobo[OnError]
attributes. Have a look. – Navarre