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
  • 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 for an example as to how your read method should behave. Commented Mar 17, 2017 at 11:29

1 Answer 1

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)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.