Class: JsonMessage

Inherits:
Object
  • Object
show all
Defined in:
lib/json_message.rb

Defined Under Namespace

Classes: DefinitionError, Error, Field, ParseError, ValidationError

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fields = {}) ⇒ JsonMessage

Returns a new instance of JsonMessage.



133
134
135
136
137
# File 'lib/json_message.rb', line 133

def initialize(fields={})
  @msg = {}
  fields.each { |name, value| set_field(name, value) }
  set_defaults
end

Class Method Details

.decode(json) ⇒ Object



67
68
69
70
71
72
73
74
75
# File 'lib/json_message.rb', line 67

def decode(json)
  begin
    dec_json = Yajl::Parser.parse(json)
  rescue => e
    raise ParseError, e.to_s
  end

  from_decoded_json(dec_json)
end

.fieldsObject



63
64
65
# File 'lib/json_message.rb', line 63

def fields
  @fields ||= {}
end

.from_decoded_json(dec_json) ⇒ Object

Raises:



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/json_message.rb', line 77

def from_decoded_json(dec_json)
  raise ParseError, "Decoded JSON cannot be nil" unless dec_json

  errs = {}

  # Treat null values as if the keys aren't present. This isn't as strict
  # as one would like, but conforms to typical use cases.
  dec_json.delete_if {|k, v| v == nil}

  # Collect errors by field
  fields.each do |name, field|
    err = nil
    if dec_json.has_key?(name.to_s)
      begin
        field.validate(dec_json[name.to_s])
      rescue ValidationError => e
        err = e.errors[name]
      end
    elsif field.required
      err = "Missing field #{name}"
    end

    errs[name] = err if err
  end

  raise ValidationError.new(errs) unless errs.empty?

  new(dec_json)
end

.optional(name, schema = nil, default = nil, &blk) ⇒ Object



111
112
113
# File 'lib/json_message.rb', line 111

def optional(name, schema = nil, default = nil, &blk)
  define_field(name, :schema => schema, :default => default, &blk)
end

.required(name, schema = nil, &blk) ⇒ Object



107
108
109
# File 'lib/json_message.rb', line 107

def required(name, schema = nil, &blk)
  define_field(name, :schema => schema, :required => true, &blk)
end

Instance Method Details

#encodeObject

Raises:



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/json_message.rb', line 139

def encode
  set_defaults

  missing_fields = {}

  self.class.fields.each do |name, field|
    if field.required && !@msg.has_key?(name)
      missing_fields[name] = "Missing field #{name}"
    end
  end

  raise ValidationError.new(missing_fields) unless missing_fields.empty?

  Yajl::Encoder.encode(@msg)
end

#extract(opts = {}) ⇒ Object



155
156
157
158
159
160
161
162
# File 'lib/json_message.rb', line 155

def extract(opts = {})
  hash = @msg.dup
  if opts[:stringify_keys]
    hash = hash.inject({}) { |memo,(k,v)| memo[k.to_s] = v; memo }.freeze
  end

  hash.freeze
end