2

I am consuming an api with .NET Core, which returns arrays of objects. But when the array contains only one object, the external API will remove the array, and paste the object directly.

I hope there is an attribute or setting which does not require me to work with JObjects, or override the JsonConverter.

Sample JSON im dealing with:

{
    "a": {
        "b": [{
            "id": 1,
            "name": "first object"
        }, {
            "id": 2,
            "name": "second object"
        }]
    }
}

Json with omitted array

{
    "a": {
        "b": {
            "id": 1,
            "name": "One object only"
        }
    }
}

This is what I am doing (simplified)

public class Response
{
    public A a { get; set; }
}

public class A
{
    public List<B> b { get; set; }
}

public class B
{
    public int id { get; set; }
    public string name { get; set; }
}

var apiResponse = await response.Content.ReadAsAsync<Response>()

I wish it would be possible that when the second JSON example is returned, that ReadAsAsync() would automatically understand that it should be converted to an array with one object of B.

The problem is that this can happen on many places in the API responses.

1

1 Answer 1

2

You can create a custom JsonConverter to check whether you are dealing with an array or a single object. The following sample shows a converter that converts to List<T>:

public class ArrayJsonConverter<T> : JsonConverter<List<T>>
{
    public override List<T> ReadJson(JsonReader reader, Type objectType, List<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartObject)
        {
            var jObj = JObject.Load(reader);
            var obj = jObj.ToObject<T>();
            var lst = new List<T>();
            lst.Add(obj);
            return lst;
        }
        else if (reader.TokenType == JsonToken.StartArray)
        {
            var jArray = JArray.Load(reader);
            return jArray.ToObject<IEnumerable<T>>().ToList();
        }
        throw new InvalidOperationException();
    }

    public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

The converter first checks whether the reader is positioned at an object or an array. Depending on that, it either creates a list with just one object or reads the array.
In order to use it, you can mark the properties with the JsonConverter attribute, e.g.:

public class A
{
    [JsonConverter(typeof(ArrayJsonConverter<B>))]
    public List<B> b { get; set; }
}
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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.