wxJSON Tutorial – Part III – Describing a Table

Preface

Here is a third part of wxJSON tutorial provided by Luciano Cattani, author and maintainer of wxJSON library.

Describing a Table with wxJSON

How many times did you use a table in your application? I know the answer: many times. So the best thing would be to write a general-purpose panel window that is capable to show every possible table and table’s format.

It is not hard to write a similar panel: we only need to implement some basic data that will be passed as parameters to the panel window:

  • the column’s names
  • the column’s alignment, if not implicit in the data type
  • the type of data in each column
  • the border thickness, if any
  • the column’s width in pixels or in panel’s width percentage, if needed
  • a bidimensional array that contains the actual data that has to be displayed

A more complex work is to define a good data structure that holds this informations and the table’s data themselves. Because we have to show many different tables in our application, there is not a general structure suitable for our needs because the data type of each column may vary from table to table. But we need something to pass as a parameter to our general-purpose table-viewer panel.

The answer could be: use a JSON formatted wxString object. We define a JSON object that contains two main objects:

  • a description of the columns
  • the content of the rows

Below you find the format of the JSON text that describes a table containing three columns and three rows:

 {
   "Border"  : 1,

   "Columns" : [ 
     {
       "Name"   : "City",
       "Width"  : 50,
       "Unit"   : "Percentage"
     },
     {
       "Name"      : "Temperature",
       "Width"     : 20,
       "Unit"      : "Percentage"
     },
     {
       "Name"      : "Date",
       "Width"     : 30,
       "Unit"      : "Percentage"
       "Alignment" : "center"
     }
  ]

   "Rows" : [
     [ "Baltimora", 20, "20 july" ],
     [ "New York", 25, "23 july" ],
     [ "Los Angeles", 29, "25 july" ]
   ]
 }

Note that there is no need to specify the type of the data contained in each column because the JSON value object already carries it.

The code for displaying a table that is described in the above JSON text is similar to this one:

 void DisplayTable( const wxString& jsonText )
 {
   wxJSONReader reader;
   wxJSONvalue  root;
   int numErrors = reader.Parse( jsonText, root );
   if ( numErrors > 0 )  {
     // if there are errors in the JSON document return
     return;
   {

   // now display the column names
   wxJSONvalue columns = root["Columns"];
   int border = root["Border"].AsInt();
   int width; string align;
   for ( int i = 0; i < columns.Size(); i++ )  {
     width = columns[i]["Width"].AsInt();
     DisplayColName( columns[i]["Name"].AsString(), width );
   }

   // and now we display the data in the rows
   // note that we use a predefined alignment for data
   // unless a specific alignment is set:
   //
   //  left for strings
   //  right for numbers

   // the bidimensional array
   wxJSONValue rows = root["Rows"];

   // the string that has to be displayed in the table's cell
   string valueString;

   // the default alignment: it is set depending on the data type
   wxJSONValue defaultAlign;

   // for all rows ...
   for ( int x = 0; x < rows.Size(); x++ )  {

     // .. and for all columns in the row
     for ( int y = 0; y < rows[x].Size(); y++ )  {
       // get the width of the column
       width = columns[y]["Width"].AsInt();

       // get the value object
       wxJSONValue value = rows[x][y];

       // check the type of the data
       wxJSONValue::wxJSONType type = value.GetType();
       switch ( type )  {
         case wxJSONTYPE_NULL :
           // display an empty string
           valueString.clear();;
           break;
         case wxJSONTYPE_INT :
         case wxJSONTYPE_UINT :
         case wxJSONTYPE_DOUBLE :
           // numeric values are right-aligned
           defaulAlign = "right";
           align = columns[y].Get( "Align", defaultAlign ).AsString();
           valueString = value.AsString();
           break;
         case wxJSONTYPE_STRING :
         case wxJSONTYPE_CSTRING :
           defaulAlign = "left";
           align = columns[y].Get( "Align", defaultAlign ).AsString();
           valueString = value.AsString();
           break;
         case wxJSONTYPE_BOOL :
           defaulAlign = "center";
           align = columns[y].Get( "Align", defaultAlign ).AsString();
           valueString = value.AsString();
           break;
       }
       // now that we have the alignment, the column's width and the 
       // value of the data as a string:
       // note that numeric data are converted to a decimal string
       // and boolean values are converted to 'TRUE' or 'FALSE' when you
       // use the wxJSONValue::AsString() memberfunction
       DisplayValue( valueString, width, align );

     }   // continue for all columns
   }     // continue for all rows
 }
[/sourcecode]
JSON format is very flexible: in future we can add new features to the application. For example we may decide that our general-purpose table-viewer panel will let the user to change the values in the table rows but only for some specific columns.

We add a new item in the Columns array descriptors: the Editable flag which is a boolean type. Example:

 "Columns" : [ 
     {
       "Name"   : "Temperature",
       "Width"  : 50,
       "Unit"   : "Percentage",
       "Editable" : true
     },

Note that this new format of our table description is compatible in both directions: it is normal that a new version of the application can read and handle old-style data but it is not very easy to maintain the old application compatible with a new data format that was introduced in a new version.

In our example, the simplicity and flexibility of JSON make the old application capable of reading the new format of JSON data. Of course, the data are not editable because the old application does not permit this operation. The old version of the application simply ignores the existance of the new Editable flag so that the JSON text can be read and processed as in the previous version.

Leave a Reply

Your email address will not be published. Required fields are marked *

Please leave these two fields as-is: