Tag Archives: JSON

Seriliasing Interfaces in JSON (or using a JsonConverter in JSON.NET)

Imagine that you have the following interface:

    public interface IProduct
    {
        int Id { get; set; }
        decimal UnitPrice { get; set; }
    }

This is an interface, and so may have a number of implementations; however, we know that every implementation will contain at least 2 fields, and what type they will be. If we wanted to serialise this, we’d probably write something like this:

        private static string SerialiseProduct(IProduct product)
        {
            string json = JsonConvert.SerializeObject(product);
            return json;
        }

If you were to call this from a console app, it would work fine:


        static void Main(string[] args)
        {
            IProduct product = new Product()
            {
                Id = 1,
                UnitPrice = 12.3m
            };

            string json = SerialiseProduct(product);
            Console.WriteLine(json);

Okay, so far so good. Now, let’s deserialise:


        private static IProduct DeserialiseProduct(string json)
        {
            IProduct product = JsonConvert.DeserializeObject<IProduct>(json);

            return product;
        }

And let’s call it:


        static void Main(string[] args)
        {
            IProduct product = new Product()
            {
                Id = 1,
                UnitPrice = 12.3m
            };

            string json = SerialiseProduct(product);
            Console.WriteLine(json);

            IProduct product2 = DeserialiseProduct(json);
            Console.WriteLine(product2.Id);
            
            Console.ReadLine();

        }

So, that runs fine:

Newtonsoft.Json.JsonSerializationException: ‘Could not create an instance of type SerialiseInterfaceJsonNet.IProduct. Type is an interface or abstract class and cannot be instantiated.

No.

Why?

The reason is that you can’t create an interface; for example:

That doesn’t even compile, but effectively, that’s what’s happening behind the scenes.

Converters

Json.Net allows the use of something called a converter. What that means is that I can inject functionality into the deserialisation process that tells Json.Net what to do with this interface. Here’s a possible converter for our class:


    class ProductConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return (objectType == typeof(IProduct));
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            return serializer.Deserialize(reader, typeof(Product));
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            serializer.Serialize(writer, value, typeof(Product));
        }
    }

It’s a relatively simple interface, you tell it how to identify your class, and then how to read and write the Json.

Finally, you just need to tell the converter to use this:


        private static IProduct DeserialiseProduct(string json)
        {
            var settings = new JsonSerializerSettings();
            settings.Converters.Add(new ProductConverter());

            IProduct product = JsonConvert.DeserializeObject<IProduct>(json, settings);

            return product;
        }

By using the settings parameter.

References

http://www.jerriepelser.com/blog/custom-converters-in-json-net-case-study-1/

Manually Parsing a JSON String Using JSON.NET

How to manually parse a JSON string using JSON.NET.

Disclaimer

If you jump straight to the references, you will find a very similar set of information, and I strongly encourage people to do so. Additionally, this is probably not the most efficient way to achieve this.

Right, on with the show

Here’s the string that I’ll be parsing, and a little code stolen directly from the link at the bottom to show what it looks like:

static void Main(string[] args)
{
    string json = "{\"documents\":[{\"keyPhrases\":[\"Test new bug\"],\"id\":\"1\"}],\"errors\":[]}";
    JsonTextReader reader = new JsonTextReader(new StringReader(json));
    while (reader.Read())
    {
        if (reader.Value != null)
        {
            Console.WriteLine("Token: {0}, Value: {1}", reader.TokenType, reader.Value);
        }
        else
        {
            Console.WriteLine("Token: {0}", reader.TokenType);
        }
    }
 
    Console.ReadLine();
}

The output for this looks like:

Using this, it’s easier to create a routine to manually parse this. Each object can be tracked by using the Start and EndObject tags. Here’s my unit test to check this works:

[TestMethod]
public void TestJSONParse()
{
    // Arrange
    string json = "{\"documents\":[{\"keyPhrases\":[\"Test new bug\"],\"id\":\"1\"}],\"errors\":[]}";
    // Act
    var result = JsonHelper.ParseResponse(json);
 
    // Assert
    Assert.AreEqual(1, result.Count());
    Assert.AreEqual(1, result.Keys.First());
    string expectedPhrase = result.Values.First().First().ToString();
    Assert.AreEqual("Test new bug", expectedPhrase, false);
}

And here’s the code itself:

/// <summary>
/// Parse the following JSON
/// {"documents":[{"keyPhrases":["Test new bug"],"id":"1"}],"errors":[]}
/// </summary>
/// <param name="response"></param>
/// <returns></returns>
public static Dictionary<int, List<string>> ParseResponse(string response)
{
    Dictionary<int, List<string>> dict = new Dictionary<int, List<string>>();
    object readerValue;
 
    if (!string.IsNullOrWhiteSpace(response))
    {
        JsonTextReader reader = new JsonTextReader(new StringReader(response));
        int? currentValue = null;
        List<string> currentList = null;
 
        while (reader.Read())
        {
            readerValue = reader.Value;
 
            switch (reader.TokenType)
            {
                case JsonToken.PropertyName:                            
                    if (readerValue.ToString() == "id")
                    {
                        reader.Read();
                        currentValue = int.Parse(reader.Value.ToString());                                
                    }
                    else if (readerValue.ToString() == "keyPhrases")
                    {
                        // Do nothing
                    }
                    else if (readerValue.ToString() == "errors")
                    {
                        currentValue = null;
                    }
                    break;
 
                case JsonToken.String:                            
                    currentList.Add(reader.Value.ToString());
                    break;
 
                case JsonToken.StartArray:
                    currentList = new List<string>();
                    break;
 
                case JsonToken.StartObject:
                    currentList = null;
                    currentValue = null;
                    break;
 
                case JsonToken.EndObject:
                    if (currentValue.HasValue)
                    {
                        dict.Add(currentValue.Value, currentList);
                    }
                    break;
            }
        }
    }
 
    return dict;
}

It is messy, and it is error prone, and it would be better done by creating classes and serialising it; however, I’d never attempted to do this manually before, and it’s generally nice to do things the hard way, that way, you can appreciate what you get from these tools.

References

http://www.newtonsoft.com/json/help/html/ReadJsonWithJsonTextReader.htm

MVVMCross – Overriding The Default Plugins

Following on from this post I discovered that I did, indeed, have a recursive reference in my game file. After a little searching, I found this excellent article on how to prevent this error, and to make the Json serializer behave rationally.

In MVVMCross, the code to serialize JSON is based on a standard plugin; it looks like this (or at least this is how I am saving my game):

public void Save()
{
    var jsonConv = Mvx.Resolve<IMvxJsonConverter>();            
    string text = jsonConv.SerializeObject(this);
    FileHelper.SaveGameFile(text);
}

The type is registered in App.cs like this:

Mvx.RegisterType<IMvxJsonConverter, MvxJsonConverter>();

What’s the fix?

The above article says the fix is this:

Settings = new JsonSerializerSettings
{
    PreserveReferencesHandling = PreserveReferencesHandling.Objects

(it does go into more detail and I encourage everyone to read it).

So this is a change to MVVM Cross

Might be.

However, you can always use your own Serializer. One of the things that I’ve come to really like about MVVM Cross if that if you don’t like something, just write your own and override that specific thing. I stole this code, verbatim, from MVVM Cross, with the single exception of the one line above:

    public class MyJSonConverter : IMvxJsonConverter
    {
        private static readonly JsonSerializerSettings Settings;

        static KMJSonConverter()
        {
            Settings = new JsonSerializerSettings
            {
                ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize,
                Converters = new List<JsonConverter>
                        {
                            new MvxEnumJsonConverter(),
                        },
                DateFormatHandling = DateFormatHandling.IsoDateFormat,
                PreserveReferencesHandling = PreserveReferencesHandling.Objects
            };
        }

        public T DeserializeObject<T>(string inputText)
        {
            return JsonConvert.DeserializeObject<T>(inputText, Settings);
        }

        public string SerializeObject(object toSerialise)
        {
            return JsonConvert.SerializeObject(toSerialise, Formatting.None, Settings);
        }

        public object DeserializeObject(Type type, string inputText)
        {
            return JsonConvert.DeserializeObject(inputText, type, Settings);
        }
    }

Now, in App.cs, just change how it is registered:

Mvx.RegisterType<IMvxJsonConverter, MyJSonConverter>();
//Mvx.RegisterType<IMvxJsonConverter, MvxJsonConverter>();

Job done. It now works!

MVVM Cross Basics – Passing Complex Parameters During Navigation

Having covered basic navigation, I found that I needed to pass my game state from view-model to view-model. I initially thought that I could simply do this as follows:

    private void CallVM2()
    {
        MyObj newObj = new MyObj();
        IMyService myService = new MyService();

		Dictionary<string, object> p = new Dictionary<string, object>()
        {
            {"MyObj", newObj},
            {"MyService", myService}
        };
		ShowViewModel<ViewModel2>(p);
    }

The code for ViewModel2:

    public void Init(Dictionary<string, object> p)
    {
    }

Anyway, it turns out you can’t. Init does get fired, but if you pass anything more complex than a string, it just bins the parameter.

The answer appears to be to create a class and to serialise it using JSON.NET:

http://stackoverflow.com/questions/19058173/passing-complex-navigation-parameters-with-mvvmcross-showviewmodel

After implementing this suggestion, I ended up with something like this:

    public abstract class BaseViewModel : MvxViewModel
    {
        private const string ParameterName = "parameter";

        public BaseViewModel()
        {
        }

        protected void ShowViewModel<TViewModel>(object parameter) where TViewModel : IMvxViewModel
        {
            var text = Mvx.Resolve<IMvxJsonConverter>().SerializeObject(parameter);
            base.ShowViewModel<TViewModel>(text);
        }

        public void Init(string parameter)
        {
            if (parameter == null || parameter.Length == 0) return;

            IMvxJsonConverter converter = Mvx.Resolve<IMvxJsonConverter>();
            NavigationParameter deserialized = converter.DeserializeObject<NavigationParameter>(parameter);
            RealInit(deserialized);
            
        }
    }

If you don’t register the converter in the IoC container (as I initially didn’t), then you’ll get this error:

A first chance exception of type ‘Cirrious.CrossCore.Exceptions.MvxIoCResolveException’ occurred in Cirrious.CrossCore.DLL

Additional information: Failed to resolve type Cirrious.CrossCore.Platform.IMvxJsonConverter

The fix:

    public abstract class BaseViewModel : MvxViewModel
    {
        private const string ParameterName = "parameter";

        public BaseViewModel()
        {
            Mvx.RegisterType<IMvxJsonConverter, MvxJsonConverter>();
        }

Now, if you override the `RealInit` method, you’ll see that the parameters are, indeed, available. However, I had a further problem; this time being with JSON.NET. As you can see from the above structure, it’s a dictionary of objects. So, when running this, it will certainly pass through the object, but it’ll just be the serialised string.

And…?

I’m pretty sure that I could get around this using a combination of generics and a custom Javascript serialisation library, but I’ve got a game to write, so I’m going to stick with declaring the Navigation parameter as follows:

   public class NavigationParameter
    {
        public MyObject ObjectParameter { get; set; }
        public MyService ServiceParameter { get; set; } 
    }

It’s worth bearing in mind that you can’t use interfaces either in the parameters; JSON.NET needs a concrete class.

Loading a Twitter Feed in WinRT

Recently, Twitter in their wisdom, discontinued the support for atom feed.  I have a couple of programs that were interrogating this, and they all suddenly (and gracefully I might add) stopped working.

The changeover is not that straightforward, especially if you don’t want to use third party libraries.

Introduction and Caveat

What I’m trying to achieve with this post is to collate all the information that I’ve gathered into a single place, so that switching from the old atom Twitter search:

string atomTweetSearchURL = string.Format("http://search.twitter.com/search.atom?q={0}", searchText);

…to the new OAuth2 can be achieved without looking anywhere else.

This is based on a Windows Store app.  There are some features that will be specific to a Store App, but I have no reason to believe this wouldn’t be generally applicable (and possible in a similar fashion) outside of the RT environment.  Having said that, there are other resources more applicable if you have access to the full .NET framework.

Finally, I have made use of lots of internet help. Where possible, I’ll link the appropriate articles, but if I forget to, just assume that the code you see here was either directly taken, or adapted from something I found online.

A last point, if you use libraries such as Linq to Twitter and JSON.NET, you’ll make your life easier; personally, I wanted to do this without a third party library.

Twitter Configuration

Previously, the URL above would allow you to simply interrogate the Twitter stream and Twitter didn’t need to know about who you were. That is now replaced. You don’t necessarily need to log-in as a user, you can use Application Only Identification. To set this up, visit https://apps.twitter.com/app/new

twitterappdetails

Only the first three boxes are required information. If you are developing a Windows 8 App then the Website can be a deep link to your application; for example, mine was here:

http://apps.microsoft.com/windows/app/geegeeeight/26d0e292-ca89-4ad6-bddc-cde3f2f9e7eb

Once you click on the button to create a new app:

CreateTwitterApp

You will be provided with a Key and a Secret. These are long strings of numbers and letters that will identify your app.

JSON Helpers

We’ll be dealing in JSON. As such, you need to be able to serialise and de-serialise JSON data. The first thing to do is to create a helper class such as follows:

    class JSonSerialiserHelper
    {

        public static T Deserialize<T>(string json)
        {
            var _Bytes = Encoding.Unicode.GetBytes(json);
            using (MemoryStream _Stream = new MemoryStream(_Bytes))
            {
                var _Serializer = new DataContractJsonSerializer(typeof(T));
                return (T)_Serializer.ReadObject(_Stream);
            }
        }

        public static string Serialize(object instance)
        {
            using (MemoryStream _Stream = new MemoryStream())
            {
                var _Serializer = new DataContractJsonSerializer(instance.GetType());
                _Serializer.WriteObject(_Stream, instance);
                _Stream.Position = 0;
                using (StreamReader _Reader = new StreamReader(_Stream)) 
                { return _Reader.ReadToEnd(); }
            }
        }
    }

You’ll also need to deal with dates, so add this, too:

        internal static DateTime ConvertDate(string dateIn)
        {
            // http://blog.kevinyu.org/2012/07/handling-json-in-net.html
            const string Const_TwitterDateTemplate = "ddd MMM dd HH:mm:ss +ffff yyyy";
            DateTime createdAt = DateTime.ParseExact(dateIn, Const_TwitterDateTemplate, new System.Globalization.CultureInfo("en-GB"));

            return createdAt;
        }

Obviously if you’re not in Britain you may wish to change the culture.

Get a Token

There is now a two step authentication; it works like this:
1. Send your application details (key and secret) to Twitter and get an Authorisation Token
2. Use the token to search Twitter with your criteria

The Key and Secret are what you obtained above when you registered your app; the code below should get you a token with that information:

        // http://stackoverflow.com/questions/22733283/twitter-oauth2-using-winrt
        private async Task<TwitAuthenticateResponse> TwitterOAuth(string key, string secret)
        {
            var client = new HttpClient();
            var uri = new Uri("https://api.twitter.com/oauth2/token");

            var encodedConsumerKey = WebUtility.UrlEncode(key);
            var encodedConsumerSecret = WebUtility.UrlEncode(secret);
            var combinedKeys = String.Format("{0}:{1}", encodedConsumerKey, encodedConsumerSecret);
            
            var utfBytes = System.Text.Encoding.UTF8.GetBytes(combinedKeys);
            var encodedString = Convert.ToBase64String(utfBytes);

            client.DefaultRequestHeaders.Add("Authorization", string.Format("Basic {0}", encodedString));

            var data = new List<KeyValuePair<string, string>> 
            { 
                new KeyValuePair<string, string>("grant_type", "client_credentials") 
            };

            var postData = new FormUrlEncodedContent(data);

            var response = await client.PostAsync(uri, postData);
            TwitAuthenticateResponse authenticationResponse;
            using (response)
            {
                if (response.StatusCode != System.Net.HttpStatusCode.OK)
                    throw new Exception("Error.  Authentication Failed.");

                var content = await response.Content.ReadAsStringAsync();
                authenticationResponse = JSonSerialiserHelper.Deserialize<TwitAuthenticateResponse>(content);
                if (authenticationResponse.token_type != "bearer")
                    throw new Exception("Wrong result type.  Authentication failed.");

                return authenticationResponse;
            }            
        }

TwitAuthenticateResponse looks like this:

    public class TwitAuthenticateResponse
    {
        public string token_type { get; set; }
        public string access_token { get; set; }        
    }

If you call that, you should have a valid token:

var auth = await TwitterOAuth("key", "secret");

Now the search

Now you have the authentication, you can use that to call the search; here’s the code:

        // http://stackoverflow.com/questions/23671600/using-a-token-to-search-on-twitter-with-oauth2
        private async Task<string> SearchTwitter(string accessToken, string srchStr)
        {
            var client = new HttpClient();
            var searchUrl = string.Format("https://api.twitter.com/1.1/search/tweets.json?q={0}", srchStr);
            var uri = new Uri(searchUrl);

            client.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", accessToken));

            HttpResponseMessage response = await client.GetAsync(uri);
            string content = await response.Content.ReadAsStringAsync();

            return content;
        }

And here’s the call:

string srch = await SearchTwitter(auth.access_token, searchText);

What to do with the results?

Okay – you can use JSON.NET as mentioned before; however, here’s a way to do it without.

First, you need to declare some classes to hold the data:

    public class TwitSearchResult
    {
        public StatusClass[] statuses { get; set; }

    }

    public class TwitUser
    {
        public string ScreenName { get; set; }
    }

    public class StatusClass
    {
        public string text { get; set; }
        public string source { get; set; }
        public TwitUser user { get; set; }
        public string created_at { get; set; }
    }

Finally, use the helper classes above to deserialise what you get back:

            TwitSearchResult srchResult = JSonSerialiserHelper.Deserialize<TwitSearchResult>(srch);

Summary

The final top level call now looks like this:

            var auth = await TwitterOAuth("key", "secret");
            string srch = await SearchTwitter(auth.access_token, searchText);

            TwitSearchResult srchResult = JSonSerialiserHelper.Deserialize<TwitSearchResult>(srch);

Conclusion

Like I said before, if I’ve used your code and not credited you then it’s not intentional. My aim was just to get all this into a single place for future reference. If you’d like me to reference anything that isn’t referenced then contact me or leave a message.