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

Small LINQ to JSON Library

, 6 Dec 2011
A small LinqToJSON library in C#, and how it works
using System.Collections.Generic;
using System.Text;




namespace Ranslant.JSON.Linq
{
    public class JObjectMember
    {
        /// <summary>
        /// Can be set only with the constructor, can be read anytime
        /// </summary>
        public string Name
        { 
            get; 
            private set;
        }

        /// <summary>
        /// Can be set only with the constructor, can be read anytime
        /// </summary>
        public IJValue Value
        {
            get;
            private set;
        }

        /// <summary>
        /// Data container class, used within JObject only
        /// </summary>
        /// <param name="name">Name of the value</param>
        /// <param name="value">value (can be any of the classes that implements the interface IJvalue)</param>
        public JObjectMember(string name, IJValue value)
        {
            Name = name;
            Value = value;
        }
    }
    
    public class JObject : IJValue
    {
        private Dictionary<string, IJValue> _members;
        
        /// <summary>
        /// Creates an empty JSON object. Use one of the Add() functions to fill it.
        /// </summary>
        public JObject()
        { }

        /// <summary>
        /// Creates a JSON object pre-filled with the jObjectMembers
        /// </summary>
        /// <param name="jObjectMembers">JSON object members, with name and value passed with the constructor of JObjectMember</param>
        public JObject(params JObjectMember[] jObjectMembers)
        {
            this.Add(jObjectMembers);
        }

        /*
         The code below is not needed because:
         1. JDocument.JDocument(JObject jObject) does the job
         2. JObject has only one field/property and it is set using Add()
          
         I am nonetheless leaving it here for educational purposes.
        */
        //internal void CopyToDocument(JDocument doc)
        //{
        //    // from http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/f7362ba9-48cd-49eb-9c65-d91355a3daee
        //    Type sourceType = this.GetType();
        //    Type destinationType = destination.GetType();

        //    foreach (PropertyInfo sourceProperty in sourceType.GetProperties())
        //    {
        //        PropertyInfo destinationProperty = destinationType.GetProperty(sourceProperty.Name);
        //        if (destinationProperty != null)
        //        {
        //            destinationProperty.SetValue(destination, sourceProperty.GetValue(this, null), null);
        //        }
        //    }
        //}


        public new string ToString()
        {
            return this.ToString(0);
        }

        public string ToString(int indentLevel)
        {
            StringBuilder sb = new StringBuilder();
            int count = _members.Count;

            sb.AppendLine(JToken.ObjectStart);
            string indent = indentLevel > 0 ? Utilities.MakeIndent(indentLevel) : string.Empty;
            
            foreach(KeyValuePair<string, IJValue> pair in _members)
            {

                sb.Append(Utilities.MakeJSONTextLine(indent,
                    // do not add the separator for the last member
                    --count > 0,
                    // for the name ({0} in the string below) we cannot use pair.key directly, because we would other wise loose the string formatting of JSON (delimiters, etc.). Therefore we use a JString.
                    string.Format("{0} {1} {2}", (new JString(pair.Key)).ToString(), JToken.ObjectMemberPairSeparator, pair.Value.ToString(indentLevel + 1))
                    ));
            }

            // one indent level back for the end delimiter
            if (indentLevel > 0)
            {
                indent = indent.Remove(0, 1);
                sb.Append(indent);
            }
            sb.Append(JToken.ObjectEnd);

            return sb.ToString();
        }

        /// <summary>
        /// Returns the amount of members in the object
        /// </summary>
        public int Count
        {
            get { return _members.Count; }
        }

        /// <summary>
        /// Returns the object member value that is associated to 'name'
        /// An exception is thrown if 'name' does not exist in the object
        /// </summary>
        /// <param name="name">name of the searched value</param>
        /// <returns>IJValue associated with 'name'</returns>
        public IJValue this[string name]
        {
            get
            { 
                return _members[name];  // maybe we should rather use TryGetValue and raise an exception if needed?
            }
        }

        /// <summary>
        /// Returns the object member value that is associated to 'name'
        /// </summary>
        /// <param name="name">name of the searched value</param>
        /// <returns>IJValue associated with 'name'</returns>
        public IJValue GetValue(string name)
        { 
            return _members[name];
        }

        /// <summary>
        /// Returns a list of all the names stored in the object, without their values
        /// </summary>
        /// <returns>a list (as IEnumerable) of string</returns>
        public IEnumerable<string> GetNames()
        {
            return _members.Keys;
        }

        /// <summary>
        /// Returns a list of all the values stored in the object, without their names
        /// </summary>
        /// <returns>a list (as IEnumerable) of IJvalue</returns>
        public IEnumerable<IJValue> GetValues()
        {
            return _members.Values;
        }

        /// <summary>
        /// Returns a list of all members stored in the object
        /// </summary>
        /// <returns>a list (as IEnumerable) of JObjectMember</returns>
        public IEnumerable<JObjectMember> GetMembers()
        {
            List<JObjectMember> list = new List<JObjectMember>(_members.Count);
            foreach (KeyValuePair<string, IJValue> pair in _members)
                list.Add(new JObjectMember(pair.Key, pair.Value));

            return list;
        }

        /// <summary>
        /// Adds JSON object members (the values and their associated name are stored in a JObjectMember object) to the JSON object
        /// </summary>
        /// <param name="jObjectMembers">a list of JObjectMember, as 'param1, param2, param3,...'</param>
        public void Add(params JObjectMember[] jObjectMembers)
        {
            // lazy creation
            if (_members == null)
                _members = new Dictionary<string, IJValue>();
            
            foreach (JObjectMember om in jObjectMembers)
            {
                this.Add(om.Name, om.Value);
            }
        }

        /// <summary>
        /// Adds one JSON object member to the object. A name cannot be added twice, it must be unique in the object.
        /// </summary>
        /// <param name="name">the name of the value</param>
        /// <param name="jValue">the value to add</param>
        public void Add(string name, IJValue jValue)
        {
            // lazy creation
            if (_members == null)
                _members = new Dictionary<string, IJValue>();

            IJValue value = null;
            if (_members.TryGetValue(name, out value))
                throw new JsonException("name '"+name+"' already defined");

            _members.Add(name, jValue);
        }
    }
}

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)

Share

About the Author

Guillaume Ranslant
Software Developer IPG
Germany Germany
since 2010: C# with WPF
since 2002: C++ (MFC / QT)
since 1995: C, Java, Pascal
 

"if a drummer can do it, anobody can" - Bruce Dickinson

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 6 Dec 2011
Article Copyright 2011 by Guillaume Ranslant
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid