Home‎ > ‎Google Sketchup‎ > ‎

Simple JSON serializer Ruby implementation

posted Nov 26, 2012, 2:32 PM by My Hand   [ updated Nov 26, 2012, 3:12 PM ]
To create a nice looking and feature rich UI for a Sketchup plugin you need to create the UI in Javascript. One of the problems you have to solve is how to pass structured data between Ruby and Javascript.

JSON would be a very intuitive way of doing this as it is string based, natively supported in Javascript and a nice and compact format that supports complex data types.

Unfortunately the version of  Ruby that ships with Sketchup does not have support for parsing and creating JSON strings. There is a Ruby Gem available http://flori.github.com/json/ but I could not get this working in the Sketchup environment.

As most of the complex data structures I want to pass is from Ruby to Javascript, and Javascript can already parse JSON, I wrote a simple Ruby class that will format Ruby objects and arrays as JSON strings. It works well for reasonable sized objects, but would probably struggle with very large data sets.

It is pretty straight forward to use.

json  = JSON.new;
jsonString = json.marshal(obj); # Where obj is a Ruby object


JSON Class

#Simple JSON formatter for Ruby implementation
#Copyright (C) <2012>  <www.KeepingMyHandIn.com>
#  
#This class is free software; you can redistribute it and/or
#modify it under the terms of the GNU Lesser General Public
#License as published by the Free Software Foundation; either
#version 2.1 of the License, or (at your option) any later version.
#
#This code is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#Lesser General Public License for more details.
#
#You should have received a copy of the GNU Lesser General Public
#License along with this library; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


class JSON

  def marshal( v )
    
    json = "";
    
    marshalValue(json, v);
    
  end

  def marshalValue(json, v)
  
    if (v.is_a? String)
    
      marshalString(json, v);
    
    elsif (v.is_a? Array)
    
      marshalArray(json, v);
    
    elsif (v.is_a? Hash)
    
      marshalArray(json, v);
    
    elsif (v.is_a? Numeric)
      
      json << v.to_s;
    
    elsif (v.is_a? TrueClass)
    
      json << "true";
    
    elsif (v.is_a? FalseClass)
    
      json << "false";
    
    else 
    
      if (v == nil)
      
        json << "null";
        
      else
      
        marshalObject(json, v);
        
      end
      
    end
    
    return json;
      
  end
  
  def marshalString(json, v)
  
    json << '"' << escape(v) << '"';
        
    return json;
  
  end

  def marshalObject(json, a)
  
    json << '{';
    
    vars = a.instance_variables;
     
    vars.each { |m|
    
      marshalString(json, m);
    
      json << ':';
      
      marshalValue(json, a.instance_variable_get(m));

      json << ',';
      
    
    }

    if (vars.size() > 0)
    
      json.chop!();
      
    end
    
    json << '}';

    return json;
  
  end

  def marshalArray(json, a)
  
    json << '[';

    a.each { |e|
    
      marshalValue(json, e);
      
      json << ',';
      
    }
    
    if (a.size() > 0)
    
      json.chop!();
      
    end
    
    json << ']';
    
    return json;
  
  end

  def escape(value)

    ret = "";
    
    value.split("").each do |c|
      
      if (/["\\\/\b\f\n\r\t]/.match( c ) )
      
        ret << '\\' << c;
        
      else
      
        ret << c;
        
      end
      
    end
    
    return ret;
    
  end
  
end