Twitter, Flex and JSON

There are libraries in several programming languages that provide access to the Twitter API. Although there’s an ActionScript 3 library for Twitter, in this tutorial we will be looking at how you can retrieve Twitter’s public timeline with a little help from another collection of ActionScript 3 utilities, the corelib library.

The result of this tutorial can be seen here (“View Source” is enabled).

Twitter’s Public Timeline

Twitter’s public timeline returns the 20 most recent statuses from non-protected users. The result is offered in four different formats (XML, JSON, RSS, Atom). The structure of the data can best be explored when we look at the XML representation of the “tweets” (Twitter speak for messages). Here’s a simplified view where the child nodes inside the status nodes have been removed:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <statuses type="array">
  3.    <status>
  4.      …
  5.    </status>
  6.    <status>
  7.      …
  8.    </status>
  9.    <status>
  10.      …
  11.    </status>
  12.    <status>
  13.      …
  14.    </status>
  15.    …
  16. </statuses>

A single status node looks like this:

  1.    <status>
  2.       <created_at>Sat May 24 17:29:46 +0000 2008</created_at>
  3.       <id>819102544</id>
  4.       <text>I also won interview in the pageant</text>
  5.       <source>web</source>
  6.       <truncated>false</truncated>
  7.       <in_reply_to_status_id></in_reply_to_status_id>
  8.       <in_reply_to_user_id></in_reply_to_user_id>
  9.       <favorited>false</favorited>
  10.       <user>
  11.          <id>3725701</id>
  12.          <name>Kelly King Anderson</name>
  13.          <screen_name>startupprincess</screen_name>
  14.          <location>Utah County</location>
  15.          <description>Mentor and Friend, Make a Wish, Make it Happen!</description>
  16.          <profile_image_url>http://s3.amazonaws.com/twitter_production/profile_images/19834292/7355f_web_normal.jpg</profile_image_url>
  17.          <url>http://www.startupprincess.com</url>
  18.          <protected>false</protected>
  19.          <followers_count>206</followers_count>
  20.       </user>
  21.    </status>

As you can see, the status node contains a user node which itself has several child nodes.

corelib‘s JSON Class

Of course, you could use ActionScript’s XML capabilities to manipulate and further process the XML data. In this tutorial though, we want to make use of the JSON class which is part of the ActionScript 3 corelib library and which facilitates both serialization and deserialization of JSON data.

Download the corelib library and make the corelib.swc file available to your Flex project. The JSON class is inside the com.adobe.serialization.json package. The class provides two static methods, encode() and decode(). The decode() method reads a JSON string and returns a native object as specified by the input string.

Creating the Demo Application

Our demo displays the public timeline in a datagrid. Here’s the code with some explanations below:

  1. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*"
  2.    layout="absolute"
  3.    creationComplete="onCreationComplete()">
  4.  
  5.    <mx:Script>
  6.       <![CDATA[
  7.          import mx.collections.ArrayCollection;
  8.          import mx.rpc.http.HTTPService;
  9.          import mx.rpc.events.ResultEvent;
  10.          import mx.rpc.events.FaultEvent;
  11.          import mx.formatters.DateFormatter;
  12.          import com.adobe.serialization.json.JSON;
  13.  
  14.          [Bindable]
  15.          private var publicTimeline:ArrayCollection;
  16.  
  17.          private function onCreationComplete():void
  18.          {
  19.             loadPublicTimeline();
  20.          }
  21.  
  22.          private function loadPublicTimeline():void
  23.          {
  24.             twitterService.send();
  25.          }
  26.  
  27.          private function onPublicTimelineResult( event:ResultEvent ):void
  28.          {
  29.             var rawData:String = String( event.result );
  30.             var arr:Array = JSON.decode( rawData ) as Array;
  31.             publicTimeline = new ArrayCollection( arr );
  32.          }
  33.  
  34.          private function onPublicTimelineFault( event:FaultEvent ):void
  35.          {
  36.             trace( event.fault.toString() );
  37.          }
  38.  
  39.          private function getFormattedDate( item:Object, column:DataGridColumn ):String
  40.          {
  41.             var dateFormatter:DateFormatter = new DateFormatter();
  42.             dateFormatter.formatString = "MMMM D, YYYY, J:NN:SS";
  43.             return dateFormatter.format( item.created_at );
  44.          }
  45.  
  46.          private function getScreenName( item:Object, column:DataGridColumn ):String
  47.          {
  48.             return item.user.screen_name;
  49.          }  
  50.  
  51.       ]]>
  52.    </mx:Script>
  53.  
  54.    <mx:HTTPService
  55.       id="twitterService"
  56.       url="http://twitter.com/statuses/public_timeline.json"
  57.       resultFormat="text"
  58.       result="onPublicTimelineResult(event)"
  59.       fault="onPublicTimelineFault(event)"
  60.       showBusyCursor="true" />
  61.  
  62.    <mx:VBox width="100%" height="100%" paddingBottom="20" paddingLeft="20" paddingRight="20" paddingTop="20">
  63.       <mx:Label text="Twitter Demo" fontSize="20" fontWeight="bold" />
  64.       <mx:DataGrid dataProvider="{ publicTimeline }" width="100%" rowCount="20">
  65.          <mx:columns>
  66.             <mx:DataGridColumn width="200" headerText="Created" labelFunction="getFormattedDate" />
  67.             <mx:DataGridColumn width="200" headerText="Screen Name" labelFunction="getScreenName" />
  68.             <mx:DataGridColumn headerText="Tweet" dataField="text" />
  69.          </mx:columns>
  70.       </mx:DataGrid>
  71.       <mx:Button label="Refresh" width="100" height="30" click="loadPublicTimeline()" />
  72.    </mx:VBox>
  73.  
  74. </mx:Application>

Lines 14-15: Twitter’s public timeline data is converted into an ArrayCollection which in turn serves as a bindable dataprovider that is used to populate the datagrid.

Lines 22-25: The loadPublicTimeline() method invokes the send() method on the HTTPService object twitterService.

Lines 27-32: The payload of the result event contains the JSON string that has been returned by the Twitter API. The decode() method converts it into an array of generic objects. The array itself is wrapped into an ArrayCollection.

Lines 39-44: This is a helper function that formats the date/time value of the created_at field.

Lines 46-49: This is another helper function that retrieves the screen_name value from the Twitter user. Please note that the user object is nested inside the status object (see the XML code above). The user object can be accessed with the usual dot syntax.

Lines 54-60: The HTTPService instance that retrieves the public timeline from Twitter’s official API URL (for more details please refer to the Twitter API documentation).

View the demo application.

Security Restrictions

If you recreate this demo application in FlexBuilder, everything should be working fine as long as you run it from your local machine. If you put the files on your server though, you will be experiencing the “Security error accessing url” error. The reason is Twitter’s cross-domain policy. If you look at Twitter’s crossdomain.xml file, you notice that it allows access only from a very few domains.

Here’s what you have to do to get around this restriction: Replace the URL in line 56

http://twitter.com/statuses/public_timeline.json

with a URL that points to a PHP proxy file on your server:

  1. <?php
  2. header("Cache-Control: no-cache, must-revalidate");
  3. header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  4. $dataUrl = "http://twitter.com/statuses/public_timeline.json?" . microtime();
  5. readfile($dataUrl);
  6. ?>

The PHP script simply reads the data from Twitter and writes it to the output buffer (the file header settings and microtime() are used to prevent caching).

I hope you enjoyed the tutorial. If you have any thoughts or suggestions, feel free to leave a comment below.

Tags: , , ,

13 Responses to “Twitter, Flex and JSON”

  1. Jascha says:

    Rad, thank you.

  2. [...] Twitter, Flex and JSON | blog.log2e.com (tags: flex) [...]

  3. Pierro says:

    Looks so damn great … i will try it.
    Thanks for sharing

  4. Fadi says:

    I have tried running your demo in flexbuilder 3 but i had the following fault message.
    Any idea?
    Thank you

    *** Violation de la sécurité Sandbox***
    Interruption de la connexion à http://twitter.com/statuses/public_timeline.json – opération interdite depuis file:///C:/Users/Flex Project/JSON/Twitter_Flex_JSON/bin-debug/Twitter_Flex_JSON.swf
    [RPC Fault faultString="Security error accessing url" faultCode="Channel.Security.Error" faultDetail="Destination: DefaultHTTP"]

  5. Carlos says:

    This solution is great.
    i used it to open my rss.
    thanks for sahring :)

  6. Hannah says:

    Thanks, good job!

  7. JacobBobby says:

    Is there something more in the php file I’m missing?
    When I call the php in firefox it look identical to the original .json file.

    I don’t get a security error, but I don’t get tweets either…just a “transferring data” message at the bottom of firefox.

    Clearly I not doing something smart here.

  8. Hannah says:

    I tried your demo but I’m having problems exporting to bin-release. It works fine when I open the swf from the bin-debug folder but when I try to run it from the bin-release folder, the app launches but there is no content. Is there something I need to do to the compiler properties?

  9. thats great that you are talking about the twitter api,a good example of searching with the twitter api is on twiogle.com because you can search on twitter and google at the same time.

  10. bigDizzle says:

    @everyone

    Also you can remove /public_timeline…… and replace it with /user_timeline/”twitterid”, replacing twitterid and quotes with your actual twitter ID. Should bring up only your feeds instead of everyone’s. Twitter should remove that cross domain policy, you-tube has it also. It’s a real pain sometimes just to create a simple tool in flex for clients. Then again, flex 3 can become a pain in itself. C’mon Flash Builder 4!

  11. Merken says:

    Thank you, i got your example working in Flash Builder 4 Beta 2 with the Flex4.0 SDK.

    Instead of using the public_timeline feed, you can use the user timeline : http://twitter.com/statuses/user_timeline.json

    This will prompt you to login, however you can send a parameter to view your timeline without logging in.
    You can do this by editing this function of yours :

    private function loadPublicTimeline():void

    {
    //For example, screen_name = AdobeSystemsNL
    var screenName:String=”AdobeSystemsNL”;
    twitterService.url=”http://twitter.com/statuses/user_timeline.json?screen_name=”+screenName;
    twitterService.send();

    }

    Nice job!

  12. Amoruso says:

    Thank you, i got your example working in Flash Builder 4 Beta 2 with the Flex4.0 SDK.

    Instead of using the public_timeline feed, you can use the user timeline : http://tsitter.com/statuses/user_timeline.json

    This will prompt you to login, however you can send a parameter to view your timeline without logging in.
    You can do this by editing this function of yours :

    private function loadPublicTimeline():void

    {
    //For example, screen_name = AdobeSystemsNL
    var screenName:String="AdobeSystemsNL";
    twitterService.url="http://twitter.com/statuses/user_timeline.json?screen_name="+screenName;
    twitterService.send();

    }

    Nice job!;

Leave a Reply