Deserialize string into property array of the deserializing type using json.net I have the input JSON

{"QtyEqualsQtyWorked":0,"ReasonCode":"IN"}


and my class is

public class LoadForMovementOpt
{
    public bool QtyEqualsQtyWorked { get; set; }
    public string[] ReasonCode { get; set; }
}


The property ReasonCode has to be array for some reasons I cannot argue with, but in json it can be both string and string[]. So I wrote a custom converter that actually works, but maybe it can improved:

class LoadForMovementConverter : JsonConverter
{
    public override bool CanConvert(Type objectType) { return true; }
    public override bool CanWrite
    {
        get
        {
            return false;
        }
    }
    public override bool CanRead
    {
        get
        {
            return true;
        }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        var reasonToken = token["ReasonCode"];

        if(reasonToken == null)
        {
            return token.ToObject(objectType);
        }

        if(reasonToken.Type == JTokenType.Array)
        {
            return token.ToObject(objectType);
        }
        else
        {
            var QtyEqualsQtyWorkedToken = token["QtyEqualsQtyWorked"];
            return 
            new LoadForMovementOpt 
            {
                QtyEqualsQtyWorked = 
                    QtyEqualsQtyWorkedToken
                        .ToObject&lt;bool&gt;(), 
                ReasonCode = 
                    new string[] 
                    {
                        reasonToken.ToObject&lt;string&gt;() 
                    }
            };
        }
    }
}


Is there any way to improve it?
Do you have access the JsonReader and JToken classes? If so, consider the following APIs. There is a lot of logic tied into the current ReadJson method which could be (IMO) better separated out of there. You would of course have to create/implement/override
the appropriate base classes and methods: Notice how a lot of the clutter is separated and moved out to a factory with the following APIs? And the respective JTokens will know exactly what to do when you send the ToObject method to it - there is no need to check for the type, or to check if it's an array because the factory will take care of that logic. The only negative is that it might be a little annoying if you have to roll your own JsonReader implementation.

// A so-so API that is marginally better
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    JToken token = JToken.LoadMovementConverter(reader);
    token.ToObject();        
}


    // even more ideal API:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    JToken token = reader.GetMovementConverterJToken();
    token.ToObject();        
}

    // create new JToken types:
public class JTokenNullReason : JToken
{   
    public override object ToObject()
    {
        throw new NotImplementedException();
    }
}

public class JTokenArray : JToken
{   
    public override object ToObject()
    {
        throw new NotImplementedException();
    }
}

public class JTokenEqualsQtyWorked : JToken
{   
    public override object ToObject()
    {
        throw new NotImplementedException();
    }
}


And then the abstract class something like this:

public abstract class JToken 
{
    public abstract object ToObject();

    public static JToken Load(JsonReader reader )
    {       
            // not ideal because an abstract ReasonCode class instance method
            // could return the required JToken via a factory method.
            // you could certainly refactor this code, or, even better: 
            // ask the reader itself to get you the correct JToken.

          string reasonCode = reader.GetReasonCode();
          switch (reasonCode)
          {
              case null:
                  return new JTokenNullReason();
                  break;
              case "Array":
                  return new JTokenArray();  
                  break;
              default:
                  return new JTokenEqualsQtyWorked();
                  break;
          }
    }
}