class Mingle::Json::JsonMingleCodec

Constants

KEY_CONSTANT
KEY_TYPE
MSG_MISSING_TYPE_KEY

Public Instance Methods

as_buffer( obj ) click to toggle source
# File lib/mingle/json.rb, line 110
    def as_buffer( obj )
        JSON.generate( from_mingle_value( obj ) )
#        JSON.generate( from_mingle_value( obj ) ).encode( "binary" )
    end
from_buffer( buf ) click to toggle source
# File lib/mingle/json.rb, line 236
def from_buffer( buf )

    not_nil( buf, :buf )
    json = BitGirder::Io.parse_json( buf )

    if json.is_a?( Hash )

        codec_raise( MSG_MISSING_TYPE_KEY ) if json.empty?

        if ( res = as_mingle_value( json, nil ) ).is_a?( MingleStruct )
            res
        else
            codec_raise( "Expected struct" ) 
        end
    else
        codec_raise( "Unexpected top level JSON value" )
    end
end

Private Instance Methods

as_mingle_value( val, path ) click to toggle source
# File lib/mingle/json.rb, line 226
def as_mingle_value( val, path )
 
    case val
        when Hash then from_json_hash( val, MingleStruct, path )
        when Array then from_json_array( val, path )
        else MingleModels.as_mingle_value( val )
    end
end
as_symbol_map( h, path ) click to toggle source
# File lib/mingle/json.rb, line 167
def as_symbol_map( h, path )
    
    res = {}

    h.each_pair do |k, v|
        unless k == KEY_TYPE
            if /^\$/ =~ k
                msg = "Unrecognized control key: #{k.inspect}"
                decode_raise( path, msg )
            else
                key_path = descend( path, k )
                id = parse_identifier( k, key_path )
                val = as_mingle_value( v, key_path )
                res[ id ] = val
            end
        end
    end

    MingleSymbolMap.create( res )
end
decode_raise( path, msg ) click to toggle source
# File lib/mingle/json.rb, line 45
def decode_raise( path, msg )
    
    msg = "#{path.format}: #{msg}" if path
    codec_raise( msg )
end
descend( path, key ) click to toggle source
# File lib/mingle/json.rb, line 116
def descend( path, key )
    path ? path.descend( key ) : ObjectPath.get_root( key )
end
enum_val_in( h, path ) click to toggle source
# File lib/mingle/json.rb, line 146
def enum_val_in( h, path )
    
    if val = h[ KEY_CONSTANT ]
        if val.is_a?( String )
            parse_identifier( val, descend( path, KEY_CONSTANT ) )
        else
            decode_raise( 
                path.descend( KEY_CONSTANT ), "Invalid constant value" )
        end
    end
end
from_json_array( arr, path ) click to toggle source
# File lib/mingle/json.rb, line 212
def from_json_array( arr, path )
    
    lp = start_list( path )

    vals = arr.map do |v|
        val = as_mingle_value( v, lp )
        lp = lp.next
        val
    end

    MingleList.new( vals )
end
from_json_hash( h, struct_cls, path ) click to toggle source
# File lib/mingle/json.rb, line 189
def from_json_hash( h, struct_cls, path )
    
    en_const = enum_val_in( h, path )
    type_ref = type_ref_in( h, path )

    if en_const 
        if type_ref 
            if h.size > 2
                decode_raise path, "Enum has one or more unrecognized keys"
            else
                MingleEnum.new( :type => type_ref, :value => en_const )
            end
        else
            decode_raise path, MSG_MISSING_TYPE_KEY
        end
    else
        flds = as_symbol_map( h, path )
        type_ref ? 
            MingleStruct.new( :type => type_ref, :fields => flds ) : flds
    end
end
from_mingle_buffer( val ) click to toggle source
# File lib/mingle/json.rb, line 71
def from_mingle_buffer( val )
    Base64.strict_encode64( val.buf )
end
from_mingle_enum( en ) click to toggle source
# File lib/mingle/json.rb, line 76
def from_mingle_enum( en )
 
    val = en.value.external_form

    if @expand_enums
        { KEY_TYPE => en.type.external_form, KEY_CONSTANT => val }
    else
        val
    end
end
from_mingle_struct( val ) click to toggle source
# File lib/mingle/json.rb, line 62
def from_mingle_struct( val )
    
    res = from_mingle_symbol_map( val.fields, {} )
    res[ KEY_TYPE ] = val.type.external_form unless @omit_type_fields

    res
end
from_mingle_symbol_map( map, res = {} ) click to toggle source
# File lib/mingle/json.rb, line 52
def from_mingle_symbol_map( map, res = {} )
    
    map.each_pair do |k, v| 
        res[ k.format( @id_format ) ] = from_mingle_value( v )
    end

    res
end
from_mingle_value( val ) click to toggle source
# File lib/mingle/json.rb, line 88
def from_mingle_value( val )
    
    case val
        when MingleString then val.to_s
        when MingleSymbolMap then from_mingle_symbol_map( val )
        when MingleStruct then from_mingle_struct( val )
        when MingleBoolean then val.as_boolean

        when MingleInt64, MingleInt32, MingleFloat64, MingleFloat32 
            val.num

        when MingleBuffer then from_mingle_buffer( val )
        when MingleTimestamp then val.rfc3339
        when MingleEnum then from_mingle_enum( val )
        when MingleList then val.map { |elt| from_mingle_value( elt ) }
        when MingleNull then nil
        when nil then nil
        else codec_raise "Can't convert to json an instance of #{val.class}"
    end
end
impl_initialize() click to toggle source
# File lib/mingle/json.rb, line 36
def impl_initialize

    if @omit_type_fields && @expand_enums
        raise OptionsError.new( 
            "Illegal combination of :omit_type_fields and :expand_enums" )
    end
end
parse_identifier( s, path ) click to toggle source
# File lib/mingle/json.rb, line 126
def parse_identifier( s, path )
    
    begin
        MingleIdentifier.parse( s )
    rescue MingleParseError => e
        decode_raise( path, e.message )
    end
end
parse_type_reference( s, path ) click to toggle source
# File lib/mingle/json.rb, line 136
def parse_type_reference( s, path )
    
    begin
        MingleTypeReference.parse( s )
    rescue MingleParseError => e
        decode_raise( path, e.message )
    end
end
start_list( path ) click to toggle source
# File lib/mingle/json.rb, line 121
def start_list( path )
    path ? path.start_list : ObjectPath.get_root_list
end
type_ref_in( h, path ) click to toggle source
# File lib/mingle/json.rb, line 159
def type_ref_in( h, path )
    
    if typ_str = h[ KEY_TYPE ]
        parse_type_reference( typ_str, descend( path, KEY_TYPE ) )
    end
end