2

I try to create custom JSON converter by using code for some answered question.

public class SingleValueArrayConverter<T> : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartObject)
        {                
            T instance = serializer.Deserialize<T>(reader);
            return new List<T>() { instance };
        }
        else if (reader.TokenType == JsonToken.StartArray)
        {
            return serializer.Deserialize<List<T>>(reader);
        }

        return null;
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

This is my sample model class.

  public class Foo
{
    [JsonProperty("type")]
    public string Type;
}

I use the following code to execute. It causes error about stack overflow.

var converter = new SingleValueArrayConverter<Foo>();

var test1 = "[{ \"type\": \"test\" }]";
var result1 = JsonConvert.DeserializeObject<List<Foo>>(test1, converter);

var test2 = "{ \"type\": \"test\" }";
var result2 = JsonConvert.DeserializeObject<List<Foo>>(test2, converter);

enter image description here

  • 1
    You're peeking at the next token, but not reading (and thus removing it from the stream). Inside the custom read/write methods, you should be using the *reader* itself. See [this answer](http://stackoverflow.com/a/8031283/563532) for an example as to how your read method should behave. – Rob Mar 17 '17 at 11:29

1 Answers1

2

The easiest way to convert any JSON to .NET object is using "ToObject" method of JToken object.

public class FooConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);

        if (token.Type == JTokenType.Array)
        {
            return token.ToObject<List<Foo>>();
        }

        var item = token.ToObject<Foo>();

        return new List<Foo> { item };
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

PS. JToken object is the base class of any JSON data so we can convert JToken object to any appropriated type.

JToken             - abstract base class     
   JContainer      - abstract base class of JTokens that can contain other JTokens
       JArray      - represents an JSON array (contains an ordered list of JTokens)
       JObject     - represents an JSON object (contains a collection of JProperties)
       JProperty   - represents a JSON property (a name/JToken pair inside a JObject)
   JValue          - represents a primitive JSON value (string, number, boolean, null)