Writing an HttpContent extension that parses json using Rx

Unanswered Writing an HttpContent extension that parses json using Rx

  • Saturday, May 05, 2012 4:15 AM
     
      Has Code

    I'm currently writing an extension method that deserializes a stream from json to an object using json.net and would like to know if i'm using the proper way to ensure that the streams and readers are properly disposed.

    My current implementation code is below:

    public static Task<T> ReadFromJsonAsAsync<T>(this HttpContent content)
    {
        return content
            .ReadAsStreamAsync()
            .ToObservable()
            .SelectMany(x => Observable.Using(() => x, s => Observable.Return(s)))
            .SelectMany(x => Observable.Using(() => new StreamReader(x), r => Observable.Return(r)))
            .SelectMany(x => Observable.Using(() => new JsonTextReader(x), r => Observable.Return(r)))
            .Select(x => { var js = new JsonSerializer(); js.Converters.Add(new IsoDateTimeConverter()); return js.Deserialize<T>(x); })
            .ToTask();
    }


All Replies

  • Saturday, May 05, 2012 12:40 PM
     
      Has Code

    Hi,

    If you're starting from task and ending in task, why not just use async/await?

    public static async Task<T> ReadFromJsonAsAsync<T>(this HttpContent content)
    {
    	var stream = await content.ReadAsStreamAsync();
    
    	using (stream)
    	using (var reader = new StreamReader(stream))
    	using (var jsonReader = new JsonTextReader(reader))
    	{
    		var js = new JsonSerializer();
    
    		js.Converters.Add(new IsoDateTimeConverter());
    
    		return js.Deserialize<T>(jsonReader);
    	}
    }

    Though if you must use Rx, then the equivalent would be this:

    return content
    	.ReadAsStreamAsync()
            .ToObservable()
    	.SelectMany(stream => Observable.Using(() => stream, 
    		s => Observable.Using(() => new StreamReader(s), 
    		reader => Observable.Using(() => new JsonTextReader(reader), 
    		jsonReader => 
    		{
    			var js = new JsonSerializer();
    			
    			js.Converters.Add(new IsoDateTimeConverter());
    
    			return Observable.Return(js.Deserialize<T>(jsonReader));
    		}))))
    	.ToTask();

    - Dave


    http://davesexton.com/blog

    • Edited by Dave Sexton Saturday, May 05, 2012 12:41 PM Small bug fix
    •  
  • Saturday, May 05, 2012 12:48 PM
     
      Has Code

    Hi,

    Since your query does only synchronous work after the inital call, here's a simpler way to achieve the same results in Rx, though I'd still recommend using async/await instead.

    return content
    	.ReadAsStreamAsync()
    	.ToObservable()
    	.Select(stream =>
    	{
    		using (stream)
    		using (var reader = new StreamReader(stream))
    		using (var jsonReader = new JsonTextReader(reader))
    		{
    			var js = new JsonSerializer();
    
    			js.Converters.Add(new IsoDateTimeConverter());
    
    			return js.Deserialize<T>(jsonReader);
    		}
    	})
    	.ToTask();

    - Dave


    http://davesexton.com/blog

  • Saturday, May 05, 2012 5:59 PM
     
     

    I'd like to be able to use async and await but the only problem is that this code needs to be hosted in azure which means the code needs to target .net 4 and needs to build using vs10 for package deployment. Currently, there is no tooling support in vs11 for azure deployment and if vs10 sees the code it will blow up. Also, the async ctp won't install properly on Windows 8.

    I'd love to hear if you've managed to deploy vs11 async code to azure. That combined with the async and await integration with rx 2.0 would make a number of our Task based interop points with Rx easier as we could await observables directly.

    The reason why I'm starting and ending with Task is to maintain the signature with the other ReadAs extension methods off HttpContent. I do like your simpler approach of using select with using statements after the async network request returns.



    • Edited by emed795 Saturday, May 05, 2012 6:09 PM
    •  
  • Sunday, May 06, 2012 5:53 PM
     
     

    Hi,

    > I'd love to hear if you've managed to deploy vs11 async code to azure

    I haven't tried.  I've got very little experience with Azure, sorry.

    - Dave


    http://davesexton.com/blog

  • Wednesday, May 09, 2012 2:28 PM