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