Using JSON to get tree data into JavaScript objects

I am using JSON to transfer data back and forth between my database and my unity app. JSON is a nice alternative to XML that is faster.

Currently I am passing (variable depth acyclic) tree structures.

I have found a C# parser called litJSON that is compatible with all .net languages. An informative thread about this can be found at : http://answers.unity3d.com/questions/531/what-is-the-easiest-json-library-to-integrate-with-unity Here you may also find a useful script for getting the data out of the JSON string. All C# coders that are thinking about using JSON as a data carrier should check it out.

But alas, I can not get it to work. My problem is that i am trying to use JavaScript and I am not able to access the objects made in C#. (Is this possible?) I've been trying for three days, and I am stuck. Can anyone point me towards a simple way of building a tree structure of objects in javascript based on a JSON string? I am a bit confused because the JSON parsers out there promising to do this are all JavaScript, not Unity JavaScript, and the eval() function does not exist in Unity Javascript (or does it?).

How can I create a javascript object tree from JSON string (similar to eval()) at runtime.

If the JSON parser script that you're trying to use is C#, and you're trying to access the results from Javascript, you are most likely running into the compilation order problem.

See this answer for details, but basically you may find that putting your JSON parser scripts into a new folder named "Plugins" (in your Assets folder), will solve your problem.

Sorry for the delay everybody. Here is an simplified version of the parser*

Trying feeding it pure string first, then get it to work using a textasset. Then finally, try to get the WWW object coroutine bastard thing to work (with yield).

And you need a class called Component (Comp) to get this to work. It should implement the following methods : setParentComponent(Comp), getComponentName():String, and a few more, you will notice them in the code.

     class JsonParser
        {
            private var str : String = null;
            private var cix : int = 0;
            private var identifiers : String = "{}[],:";
            private var debug : boolean =false;
            private var arr:Array =  new Array();

        function Parse( json : String )
        {

            str = json;
            cix = 0;

            out( str );
        var componentRoot = new Comp();

        ReadObject(componentRoot);

        }
    function ReadObject(intoComp:Comp) : Array
        {
            str.Trim();

            while ( cix < str.length )
            {

                if ( ReadTo( "{" ) == "Component" )
                {

                    comp = ReadComponent(intoComp);
                    if ( comp ){

                        comp.setParentComponent(intoComp);
                        break;
                    }else{
                        Error( "Adding Assembly failed!" );
                        break;
                    }
                }
                else
                {
                    Error( "Assembly expected" );
                    return null;
                }

                if ( NextIdentifier() == "," ){
                    ReadTo(",");
                }
            }

        }

        function ReadComponent(parentComp :Comp) 
            {
                var comp : Comp = new Comp();
            //  Out("Adding new component under "+ parentComp.getComponentName()+);

                while ( ReadyAttribute() )
                {
                    var attrName = ReadTo( ":" );

                    switch( attrName )
                    {
                    case "name":
                        comp.setComponentName(ReadString());
                        break;

                    case "children":
                        ReadComponentChildren( comp);
                        break;

                    case "assetLink":
                        comp.setAssetLink(ReadString());
                        break;

                    case "x":
                        comp.setXoffset(ReadFloat());
                        break;
                    case "y":
                        comp.setYoffset(ReadFloat());
                        break;
                    case "z":
                        comp.setZoffset(ReadFloat());
                        break;  
                    case "h":
                        comp.setAYoffset(ReadFloat());
                        break;
                    case "p":
                        comp.setAXoffset(ReadFloat());
                        break;
                    case "b":
                        comp.setAZoffset(ReadFloat());
                        break;
                    default:
                        Error( "Unidentified Component attribue: '" + attrName + "'");
                        ReadToAny("},");
                        --cix;
                        break;
                    }
                }

                if ( NextIdentifier() == "}" )
                {
                    ReadTo( "}" );
                }
                else
                    Error( "'}' or ':' expected" );

            }

            function ReadComponentChildren( parent : Comp)
            {
                if ( NextIdentifier() == "[" )
                {
                    ReadTo("[");

                    while( NextIdentifier() != "]" )
                    {
                        var objName = ReadTo( "{" );

                        switch( objName )
                        {           

                        case "Component":
                            ReadComponent(parent);
                            componentsAdded ++;
                            break;

                        if ( NextIdentifier() == "," ){
                            ReadTo( "," );
                        }
                    }
                    ReadTo("]");
                }
                else
                {
                    Error( "'[' expected");
                }
            }

            function ReadTo( identifier : String )
            {
                var pos : int       = str.IndexOf( identifier, cix );       // Find first occurance of identifier after current position.
                var length : int    = pos - cix;                            // Find distance from current position to identifier ( size of substring )
                var result : String = str.Substring( cix, length ).Trim();  // Get substring and remove whitespace.
                cix = pos + 1;                                              // Update current position to include identifier.

                out( "Read: " + result );
                return result;
            }

            function ReadToAny( identifiers : String )
            {
                var pos : int        = str.IndexOfAny( identifiers.ToCharArray(), cix );
                var length : int     = pos - cix;
                var result : String = str.Substring( cix, length ).Trim();  
                cix = pos + 1;  

                out( "Read: " + result );

                return result;
            }

            function NextIdentifier()
            {
                if (cix < str.Length){
                    var pos : int       = str.IndexOfAny( identifiers.ToCharArray(), cix );
                    if (pos < str.Length){
                        var result : char   = str.Chars[pos];
                        return result;
                    }
                }

            }

            function ReadString()
            {
                var begin : int     = str.IndexOf( "\"", cix ) + 1;
                var end : int       = str.IndexOf( "\"", begin );
                var length : int    = end - begin;

                var string : String = str.Substring( begin, length );
                cix = end + 1;

                out( "String: " + string );

                return string;
            }

            function ReadInteger()
            {
                var numbers : String    = "0123456789-";
                var delimit : String    = " ,
]}";
                var begin : int         = str.IndexOfAny( numbers.ToCharArray(), cix );
                var end : int           = str.IndexOfAny( delimit.ToCharArray(), begin );
                var length : int        = end - begin;

                var numStr : String     = str.Substring( begin, length );
                var valueAsFloat :float     = parseFloat( numStr );
                var value:int = Mathf.Floor(valueAsFloat);
                cix = end;

                out( "Integer: " + value );

                return value;
            }

            function ReadFloat()
            {
                var numbers : String    = "0123456789.-";
                var delimit : String    = " .
}]";
                var begin : int         = str.IndexOfAny( numbers.ToCharArray(), cix );
                var end : int           = str.IndexOfAny( delimit.ToCharArray(), begin );
                var length : int        = end - begin;
                var numStr : String = str.Substring( begin, length );
                var value : float       = parseFloat( numStr );

                cix = end;

                out( "Float: " + value );

                return value;
            }
            function ReadBoolean():boolean{

                var numbers : String    = "0123456789.-";
                var delimit : String    = " .
}]";
                var begin : int         = str.IndexOfAny( numbers.ToCharArray(), cix );
                var end : int           = str.IndexOfAny( delimit.ToCharArray(), begin );
                var length : int        = end - begin;
                var value : String  = str.Substring( begin, length );

                switch (str){
                            case  "true" :
                            cix = end;
                            return true;
                    break;
                            case  "false" :
                            cix = end;
                            return false;
                    break;

                }

                out( "Float: " + value );

            }

            function ReadyAttribute()
            {       
                if ( NextIdentifier() == "," )
                    cix = str.IndexOf(",", cix) + 1;

                if ( NextIdentifier() == ":" )
                    return true;

                if ( NextIdentifier() == "}" )
                    return false;
            }

            function Error( msg : String )
            {
                    Debug.Log( "ERROR: " + msg + " at (" + cix + ") : " + str.Substring( cix, Mathf.Min( str.length - cix, 100) ).Trim() + "..." );
            }
            function Warning( msg : String )
            {
                    Debug.Log( "Warning: " + msg + " at (" + cix + ") : " + str.Substring( cix, Mathf.Min( str.length - cix, 100) ).Trim() + "..." );
            }
            function out(msg:String){
                if(debug){
                    Debug.Log( "MESSAGE: " + msg + " at (" + cix + ") : " + str.Substring( cix, Mathf.Min( str.length - cix, 100) ).Trim() + "..." );
                }
            }
}

I've also written a simple parser, which I think might be easier to use. It's up on the UnifyCommunity Wiki. Check it out.