Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

fastJSON

, 14 Sep 2014
Smallest, fastest polymorphic JSON serializer (with Silverlight4 and MonoDroid support)
consoletest-noexe.zip
consoletest.zip
fastjson-noexe.zip
fastJSON.snk
fastjson.zip
fastJSON.snk
fastJSON_2.0.28.1.zip
Consoletest
fastJSON
fastJSON.snk
README.md
UnitTests.nunit
UnitTests
Properties
fastjson_v1.1-noexe.zip
fastJSON_v1.1.zip
Properties
fastjson_v1.2-noexe.zip
fastJSON_v1.2.zip
fastjson_v1.3-noexe.zip
fastJSON_v1.3.zip
fastjson_v1.4-noexe.zip
fastJSON_v1.4.zip
fastjson_v1.5-noexe.zip
fastJSON_v1.5.zip
fastjson_v1.6-noexe.zip
fastJSON_v1.6.zip
fastjson_v1.7-noexe.zip
fastjson_v1.7.5-noexe.zip
fastJSON_v1.7.5.zip
fastjson_v1.7.6-noexe.zip
fastJSON_v1.7.6.zip
fastjson_v1.7.7-noexe.zip
fastjson_v1.7.7-silverlight4-noexe.zip
fastJSON_v1.7.7-SilverLight4.zip
fastJSON_v1.7.7.zip
fastJSON_v1.7.zip
fastjson_v1.8-noexe.zip
fastJSON_v1.8.zip
fastjson_v1.9-noexe.zip
fastjson_v1.9.1-noexe.zip
fastJSON_v1.9.1.zip
fastjson_v1.9.2-noexe.zip
fastjson_v1.9.2.zip
fastjson_v1.9.3-noexe.zip
fastJSON_v1.9.3.zip
fastjson_v1.9.4-noexe.zip
fastJSON_v1.9.4.zip
fastjson_v1.9.6-noexe.zip
fastJSON_v1.9.6.zip
fastjson_v1.9.7-noexe.zip
fastJSON_v1.9.7.zip
fastjson_v1.9.8-noexe.zip
fastJSON_v1.9.8.zip
fastjson_v1.9.9-noexe.zip
fastJSON_v1.9.9.zip
fastJSON_v1.9.zip
fastjson_v2.0.0-noexe.zip
UnitTests.nunit
fastJSON_v2.0.0.zip
UnitTests.nunit
fastjson_v2.0.1-noexe.zip
UnitTests.nunit
fastJSON_v2.0.1.zip
UnitTests.nunit
fastjson_v2.0.10-noexe.zip
UnitTests.nunit
fastJSON_v2.0.10.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.11-noexe.zip
UnitTests.nunit
fastJSON_v2.0.11.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.12-noexe.zip
UnitTests.nunit
fastJSON_v2.0.12.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.13-noexe.zip
UnitTests.nunit
fastJSON_v2.0.13.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.14-noexe.zip
UnitTests.nunit
fastJSON_v2.0.14.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.15-noexe.zip
UnitTests.nunit
fastJSON_v2.0.15.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.16-noexe.zip
UnitTests.nunit
fastJSON_v2.0.16.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.17-noexe.zip
UnitTests.nunit
fastJSON_v2.0.17.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.18-noexe.zip
UnitTests.nunit
fastJSON_v2.0.18.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.19-noexe.zip
UnitTests.nunit
fastJSON_v2.0.19.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.2-noexe.zip
UnitTests.nunit
fastJSON_v2.0.2.zip
UnitTests.nunit
fastjson_v2.0.20-noexe.zip
UnitTests.nunit
fastJSON_v2.0.20.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.21-noexe.zip
UnitTests.nunit
fastJSON_v2.0.21.zip
UnitTests.nunit
fastJSON-SL.v11.suo
fastJSON.nuspec
fastjson_v2.0.22-noexe.zip
fastJSON.nuspec
README.md
UnitTests.nunit
fastJSON_v2.0.22.zip
fastJSON.nuspec
README.md
UnitTests.nunit
fastJSON.snk
fastjson_v2.0.23-noexe.zip
README.md
UnitTests.nunit
fastJSON_v2.0.23.zip
README.md
UnitTests.nunit
fastJSON.snk
fastjson_v2.0.24-noexe.zip
README.md
UnitTests.nunit
fastJSON_v2.0.24.zip
README.md
UnitTests.nunit
fastJSON.snk
fastjson_v2.0.25-noexe.zip
README.md
UnitTests.nunit
fastJSON_v2.0.25.zip
README.md
UnitTests.nunit
fastJSON.snk
fastjson_v2.0.26-noexe.zip
README.md
UnitTests.nunit
fastJSON_v2.0.26.zip
README.md
UnitTests.nunit
fastJSON.snk
fastjson_v2.0.27-noexe.zip
README.md
UnitTests.nunit
fastJSON_v2.0.27.zip
README.md
UnitTests.nunit
fastJSON.snk
fastJSON_v2.0.28.zip
fastJSON.snk
Properties
README.md
UnitTests.nunit
fastjson_v2.0.3-noexe.zip
UnitTests.nunit
fastJSON_v2.0.3.zip
UnitTests.nunit
fastjson_v2.0.4-noexe.zip
UnitTests.nunit
fastjson_v2.0.4.zip
UnitTests.nunit
fastjson_v2.0.5-noexe.zip
UnitTests.nunit
fastJSON_v2.0.5.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.6-noexe.zip
UnitTests.nunit
fastJSON_v2.0.6.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.7-noexe.zip
UnitTests.nunit
fastJSON_v2.0.7.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.8-noexe.zip
UnitTests.nunit
fastJSON_v2.0.8.zip
UnitTests.nunit
fastJSON.nuspec
fastjson_v2.0.9-noexe.zip
UnitTests.nunit
fastJSON_v2.0.9.zip
UnitTests.nunit
fastJSON.nuspec
fastJSON_v2.1.0.zip
fastJSON.snk
README.md
UnitTests.nunit
fastJSON_v2.1.1.zip
fastJSON.snk
README.md
UnitTests.nunit
fastJSON_v2.1.2.zip
fastJSON.snk
README.md
UnitTests.nunit
fastJSON_v2.1.3.zip
fastJSON.snk
README.md
UnitTests.nunit
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

namespace fastJSON
{
	/// <summary>
	/// This class encodes and decodes JSON strings.
	/// Spec. details, see http://www.json.org/
	/// 
	/// JSON uses Arrays and Objects. These correspond here to the datatypes ArrayList and Hashtable.
	/// All numbers are parsed to doubles.
	/// </summary>
	internal class JsonParser
	{
		enum Token
		{
			None = -1,           // Used to denote no Lookahead available
			Curly_Open,
			Curly_Close,
			Squared_Open,
			Squared_Close,
			Colon,
			Comma,
			String,
			Number,
			True,
			False,
			Null
		}
		
		readonly char[] json;
		readonly StringBuilder s = new StringBuilder();
		Token lookAheadToken = Token.None;
		int index;
		
		internal JsonParser(string json)
		{
			this.json = json.ToCharArray();
		}

		public object Decode()
		{
			return ParseValue();
		}

		private Dictionary<string,object> ParseObject()
		{
			Dictionary<string, object> table = new Dictionary<string, object>();

			ConsumeToken(); // {

			while (true)
			{
				switch (LookAhead())
				{

					case Token.Comma:
						ConsumeToken();
						break;

					case Token.Curly_Close:
						ConsumeToken();
						return table;

					default:
						{

							// name
							string name = ParseString();

							// :
							if (NextToken() != Token.Colon)
							{
								throw new Exception("Expected colon at index " + index);
							}

							// value
							object value = ParseValue();

							table[name] = value;
						}
						break;
				}
			}
		}

		private ArrayList ParseArray()
		{
			ArrayList array = new ArrayList();

			ConsumeToken(); // [

			while (true)
			{
				switch (LookAhead())
				{

					case Token.Comma:
						ConsumeToken();
						break;

					case Token.Squared_Close:
						ConsumeToken();
						return array;

					default:
						{
							array.Add(ParseValue());
						}
						break;
				}
			}
		}

		private object ParseValue()
		{
			switch (LookAhead())
			{
				case Token.Number:
					return ParseNumber();

				case Token.String:
					return ParseString();

				case Token.Curly_Open:
					return ParseObject();

				case Token.Squared_Open:
					return ParseArray();

				case Token.True:
					ConsumeToken();
					return true;

				case Token.False:
					ConsumeToken();
					return false;

				case Token.Null:
					ConsumeToken();
					return null;
			}

			throw new Exception("Unrecognized token at index" + index);
		}

		private string ParseString()
		{
			ConsumeToken(); // "

			s.Length = 0;

			int runIndex = -1;

			while (index < json.Length)
			{
				var c = json[index++];

				if (c == '"')
				{
					if (runIndex != -1)
					{
						if (s.Length == 0)
							return new string(json, runIndex, index - runIndex - 1);

						s.Append(json, runIndex, index - runIndex - 1);
					}
					return s.ToString();
				}

				if (c != '\\')
				{
					if (runIndex == -1)
						runIndex = index - 1;

					continue;
				}

				if (index == json.Length) break;

				if (runIndex != -1)
				{
					s.Append(json, runIndex, index - runIndex - 1);
					runIndex = -1;
				}

				switch (json[index++])
				{
					case '"':
						s.Append('"');
						break;

					case '\\':
						s.Append('\\');
						break;

					case '/':
						s.Append('/');
						break;

					case 'b':
						s.Append('\b');
						break;

					case 'f':
						s.Append('\f');
						break;

					case 'n':
						s.Append('\n');
						break;

					case 'r':
						s.Append('\r');
						break;

					case 't':
						s.Append('\t');
						break;

					case 'u':
						{
							int remainingLength = json.Length - index;
							if (remainingLength < 4) break;
							
							// parse the 32 bit hex into an integer codepoint
							uint codePoint;

							if (!UInt32.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codePoint))
							{
								throw new Exception("Failed to decode unicode char at index " + index);
							}

							// convert the integer codepoint to a unicode char and add to string
							s.Append(Char.ConvertFromUtf32((int) codePoint));

							// skip 4 chars
							index += 4;
						}
						break;
				}
			}

			throw new Exception("Unexpectedly reached end of string");
		}


		private string ParseNumber()
		{
			ConsumeToken();

			// Need to start back one place because the first digit is also a token and would have been consumed
			var startIndex = index - 1;

			do
			{
				var c = json[index];

				if ((c >= '0' && c <= '9') || c == '.' || c == '-' || c == '+' || c == 'e' || c == 'E')
				{
					if (++index == json.Length) throw new Exception("Unexpected end of string whilst parsing number");
					continue;
				}

				break;
			} while (true);

			return new string(json, startIndex, index - startIndex);
		}

		private Token LookAhead()
		{
			if (lookAheadToken != Token.None) return lookAheadToken;

			return lookAheadToken = NextTokenCore();
		}

		private void ConsumeToken()
		{
			lookAheadToken = Token.None;
		}

		private Token NextToken()
		{
			var result = lookAheadToken != Token.None ? lookAheadToken : NextTokenCore();

			lookAheadToken = Token.None;

			return result;
		}

		private Token NextTokenCore()
		{
			char c;

			// Skip past whitespace
			do
			{
				c = json[index];

				if (c > ' ') break;
				if (c != ' ' && c != '\t' && c != '\n' && c != '\r') break;

			} while (++index < json.Length);

			if (index == json.Length)
			{
				throw new Exception("Reached end of string unexpectedly");
			}
			
			c = json[index];