0

I have a json that I am deserializing by using NewtonSoftJson Json library as shown below:

public async Task InvokeAsync(HttpContext httpContext, ISchema schema)
{
    ...
    var request = Deserialize<GraphQLRequest>(httpContext.Request.Body);
    ....
}

public static T Deserialize<T>(Stream s)
{
    using (var reader = new StreamReader(s))
    using (var jsonReader = new JsonTextReader(reader))
    {
        var ser = new JsonSerializer();
        return ser.Deserialize<T>(jsonReader);
    }
}

Now I am trying to use System.Text.Json library to deserialize asynchronously so I read their docs and they do have DeserializeAsync method which I can use but when I replace content of above method like below then I get compilation error -

public static T Deserialize<T>(Stream s)
{
  return JsonSerializer.DeserializeAsync<GraphQLRequest>(s, new JsonSerializerOptions
      {
          PropertyNameCaseInsensitive = true
      }
  );
}

Error I get is -

Cannot convert expression type 'System.Threading.Tasks.ValueTask<App.Api.Kestrel.GraphQLRequest?>' to return type 'T'

I am new to dotnet world so kinda confuse what is wrong I am doing here?

1 Answer 1

4
  1. public static T Deserialize<T>(Stream s) is a generic method where T is type parameter which is passed by user, so you need to deserialize to T, not to GraphQLRequest.

  2. async methods usually (but not always) retrun Task's, so you need to change your signature and implementation accordingly resulting in:

public static async Task<T> Deserialize<T>(Stream s)
{
  return await JsonSerializer.DeserializeAsync<T>(s, new JsonSerializerOptions
      {
          PropertyNameCaseInsensitive = true
      }
  );
}

And then pass concrete type in the invocation (and use await):

public async Task InvokeAsync(HttpContext httpContext, ISchema schema)
{
    ...
    GraphQLRequest request = await Deserialize<GraphQLRequest>(httpContext.Request.Body);
    ....
}

Since JsonSerializer.DeserializeAsync returns a ValueTask another option is to pass it through without awaiting:

public static ValueTask<T> Deserialize<T>(Stream s)
{
  return JsonSerializer.DeserializeAsync<T>(s, new JsonSerializerOptions
      {
          PropertyNameCaseInsensitive = true
      }
  );
}

The calling code will not change.

Sign up to request clarification or add additional context in comments.

3 Comments

Now it makes sense as I understood what I was missing. Also if my json fails to deserialize then System.Text.Json library will throw System.Text.Json.JsonException always or is there any case where it can throw some other exceptions for deserialization? I was looking at the docs and source code but couldn't see it clearly what it will throw so I wanted to make sure on that. But when I read JsonException class there it is clearly mentioned so just wanted to make sure
@AndyP documentation for DeserializeAsync linked in answer lists exceptions thrown by the method,
Note from PropertyNameCaseInsensitive: "There is a performance cost associated with case-insensitive comparison (that is, when PropertyNameCaseInsensitive is true)."

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.