codeputer
codeputer

Reputation: 2028

Dynamic / parsing of Json Objects

In the following snippet I do not understand the difference between the code underneath the "//this fails", and the code under "//this works" (which is provided as boilerplate code when creating an Azure function.) NOTE: I realize that the cast to object isn't necessary, BUT ReadAsAsync returns object....

public static class FunctionTest
{
    [FunctionName("TestFunction")]
    public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestMessage req, TraceWriter log)
    {
        log.Info("C# HTTP trigger function processed a request.");

        // parse query parameter
        string name = req.GetQueryNameValuePairs()
          .FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
          .Value;

        //if nothing in the query parameter - lets' look into the body
        if (name == null)
        {
            //this fails
            dynamic abc = (object) @"{""name"":""test""}";
            string test = abc?.name;

            // this works
            dynamic data = await req.Content.ReadAsAsync<object>();
            name = data?.name;
        }

        return name == null
          ? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
          : req.CreateResponse(HttpStatusCode.OK, "Hello " + name);
    }
}

Upvotes: 1

Views: 540

Answers (1)

DavidG
DavidG

Reputation: 118957

The first line:

dynamic abc = (object) @"{""name"":""test""}";

will take a string value and cast it into an object. That doesn't mean that it will treat the string as JSON and make a new dynamic object with a name property. It's still a string and the contents don't matter.

The second line however:

dynamic data = await req.Content.ReadAsAsync<object>();

calls the ReadAsAsync method with a generic type of object. This actually gives you a JObject cast as an object with various properties meaning that you could do this:

name = data["name"];

And because it is dynamic, that effectively translates your code into the above. However, almost every time I see dynamic, it's a code smell and this is no difference. Instead make a concrete class with the right properties and use that. That way you will have compile time type checking instead of relying on the dynamic object. For example:

public class Foo    {
    public string Name { get; set; }
}

And use it like this:

Foo data = await req.Content.ReadAsAsync<Foo>();

Upvotes: 3

Related Questions