1

I have the following JSON to POST to my Web API endpoint.

[
    {
        "name": "REGION",
        "value": ["MA", "SE", "SW"]
    }
]

The Web API endpoint is as follows

public class Parameter
{
    public string Name { get; set; }
    // Value can be string, string[], int, or int[]
    public dynamic Value { get; set; }
}

[Route("{chart}/data/")]
[HttpPost]
public IHttpActionResult GetData(string chart, IList<Parameter> parameters)
{
    // ... do stuff ...
}

Whenever value in the JSON is an array the deserialized parameter's Value is a JArray rather than an array of string, int, etc. However, if value is a simply a string or number then Value in the deserialized parameters is also a string or a number.

What gives? Why isn't the array in the JSON being deserialized into an array of the proper type?

4
  • 1
    That is how the Json.Net was designed. Value is dynamic. the framework will choose the least common denominator. Without a strongly typed object to bind to the model wont know what to convert the data to. Commented Dec 12, 2018 at 22:58
  • This feels like an XY problem with a bigger issue around the design. What is this ultimately going to be used for? Why would such varying data be sent to that action? Commented Dec 12, 2018 at 22:59
  • If you don't want "value" to be deserialized into JObject or JArray, you could manually convert to the conventional .Net types instead. See How do I use JSON.NET to deserialize into nested/recursive Dictionary and List? and JSON.net serializes a json array into a JArray when the destination is an object. How can I change that?. In fact this may be a duplicate of one or both; agree? Commented Dec 12, 2018 at 23:05
  • @Nkosi The endpoint accepts one or more parameters. Each parameter's value may be an int or a string. Ultimately, these are used in a where clause in SQL query to return data. Originally each parameter could have a single value. This worked well for several years. Recently, requirements changed and each parameter may have multiple values (all of the same type). Commented Dec 13, 2018 at 14:07

1 Answer 1

1

This was my solution. It "corrects" for JArray by inspecting the Value type after deserialization and converting it to the appropriate string[].

public class Parameter
{
    public string Name { get; set; }
    public dynamic Value { get; set; }

    [OnDeserialized]
    public void OnDeSerialized(StreamingContext context)
    {
        Type type = this.Value.GetType();
        if (type == typeof(JArray)) 
        {
            var value = (this.Value as JArray).ToObject(typeof(string[]));
            this.Value = value;
        }
    }
}
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.