Click here to Skip to main content
15,885,757 members
Articles / Programming Languages / Markdown

APJSON

Rate me:
Please Sign up or sign in to vote.
4.67/5 (5 votes)
28 Aug 2013CPOL13 min read 41.6K   1.2K   34  
This is an alternative for "fastJSON"
using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using Apolyton.FastJson.Data;
using Apolyton.FastJson.Serialization;

namespace Apolyton.FastJson
{
    /// <summary>
    /// This class decodes JSON strings. The root level object is always a mutable json array or a mustable json object. 
    /// Nested types are also mutables, value types are roghly parsed into long, double etc.
    /// Spec. details, see http://www.json.org/
    /// </summary>
    /// <remarks>
    /// http://www.codeproject.com/Articles/159450/fastJSON
    /// </remarks>
    internal class JsonHybridDeserializer : JsonDeserializer
    {
        private Encoding _encoding;

        /// <summary>
        /// Creates a parser for the given json string. 
        /// </summary>
        /// <param name="ignorecase"></param>
        internal JsonHybridDeserializer(JsonParameters parameters)
        {
            _encoding = parameters.Encoding;
        }

        /// <summary>
        /// Deserializes an input stream and returns a mutable json object or a mutable json array.
        /// </summary>
        /// <param name="inputStream"></param>
        /// <returns></returns>
        public Object Deserialize(Stream inputStream)
        {
            StreamReader reader = new StreamReader(inputStream, _encoding);
            String jsonString = reader.ReadToEnd();

            return Deserialize(ref jsonString);
        }

        /// <summary>
        /// Returns the object represented by the string at construction time.
        /// </summary>
        /// <returns></returns>
        public IEnumerable Deserialize(ref string jsonString)
        {
            this._jsonOriginal = jsonString.ToCharArray();
            this._index = 0;

            return (IEnumerable) ParseValue();
        }

        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 SerializationException("Unrecognized token at index" + _index);
        }

        private MutableJsonObject ParseObject()
        {
            MutableJsonObject table = new MutableJsonObject();

            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 SerializationException("Expected colon at index " + _index);
                            }

                            // value
                            object value = ParseValue();

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

        private MutableJsonArray ParseArray()
        {
            MutableJsonArray array = new MutableJsonArray();
            ConsumeToken(); // [

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

                    case Token.Comma:
                        ConsumeToken();
                        break;

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

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

        private object 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;
            bool dec = false;

            do
            {
                var c = _jsonOriginal[_index];

                if ((c >= '0' && c <= '9') || c == '.' || c == '-' || c == '+' || c == 'e' || c == 'E')
                {
                    if (c == '.' || c == 'e' || c == 'E')
                    {
                        dec = true;
                    }

                    if (++_index == _jsonOriginal.Length)
                    {
                        break;                        //throw new Exception("Unexpected end of string whilst parsing number");
                    }

                    continue;
                }

                break;

            } while (true);

            string s = new string(_jsonOriginal, startIndex, _index - startIndex);

            if (dec)
            {
                return double.Parse(s, NumberFormatInfo.InvariantInfo);
            }

            return long.Parse(s);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions