Class: CloudEvents::JsonFormat

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

Overview

An implementation of JSON format and JSON batch format.

Supports the CloudEvents 0.3 and CloudEvents 1.0 variants of this format. See https://github.com/cloudevents/spec/blob/v0.3/json-format.md and https://github.com/cloudevents/spec/blob/v1.0/json-format.md.

Instance Method Summary collapse

Instance Method Details

#decode_data(spec_version: nil, content: nil, content_type: nil, **_other_kwargs) ⇒ Hash?

Decode an event data object from a JSON formatted string. See Format#decode_data for a general description.

Expects :spec_version, :content and :content_type arguments, and will decline the request unless all three are provided.

If decoding succeeded, returns a hash with the following keys:

  • :data (Object) The payload object to set as the data attribute.
  • :content_type (ContentType) The content type to be set as the datacontenttype attribute.

Parameters:

  • content (String) (defaults to: nil)

    Serialized content to decode.

  • content_type (CloudEvents::ContentType) (defaults to: nil)

    The input content type.

Returns:

  • (Hash)

    if accepting the request.

  • (nil)

    if declining the request.

Raises:



123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/cloud_events/json_format.rb', line 123

def decode_data spec_version: nil, content: nil, content_type: nil, **_other_kwargs
  return nil unless spec_version
  return nil unless content
  return nil unless json_content_type? content_type
  unless spec_version =~ /^0\.3|1(\.|$)/
    raise SpecVersionError, "Unrecognized specversion: #{spec_version}"
  end
  data = ::JSON.parse content
  { data: data, content_type: content_type }
rescue ::JSON::JSONError
  raise FormatSyntaxError, "JSON syntax error"
end

#decode_event(content: nil, content_type: nil, data_decoder: nil, **_other_kwargs) ⇒ Hash?

Decode an event or batch from the given input JSON string. See Format#decode_event for a general description.

Expects :content and :content_type arguments, and will decline the request unless both are provided.

If decoding succeeded, returns a hash with one of the following keys:

  • :event (Event) A single event decoded from the input.
  • :event_batch (Array of Event) A batch of events decoded from the input.

Parameters:

  • content (String) (defaults to: nil)

    Serialized content to decode.

  • content_type (CloudEvents::ContentType) (defaults to: nil)

    The input content type.

  • data_decoder (#decode_data) (defaults to: nil)

    Optional data field decoder, used for non-JSON content types.

Returns:

  • (Hash)

    if accepting the request.

  • (nil)

    if declining the request.

Raises:



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/cloud_events/json_format.rb', line 41

def decode_event content: nil, content_type: nil, data_decoder: nil, **_other_kwargs
  return nil unless content && content_type&.media_type == "application" && content_type&.subtype_format == "json"
  case content_type.subtype_base
  when "cloudevents"
    event = decode_hash_structure ::JSON.parse(content), charset: charset_of(content), data_decoder: data_decoder
    { event: event }
  when "cloudevents-batch"
    charset = charset_of content
    batch = Array(::JSON.parse(content)).map do |structure|
      decode_hash_structure structure, charset: charset, data_decoder: data_decoder
    end
    { event_batch: batch }
  end
rescue ::JSON::JSONError
  raise FormatSyntaxError, "JSON syntax error"
end

#decode_hash_structure(structure, charset: nil, data_decoder: nil) ⇒ CloudEvents::Event

Decode a single event from a hash data structure with keys and types conforming to the JSON envelope.

Parameters:

  • structure (Hash)

    An input hash.

  • charset (String) (defaults to: nil)

    The charset of the original encoded JSON document if known. Used to provide default content types.

  • data_decoder (#decode_data) (defaults to: nil)

    Optional data field decoder, used for non-JSON content types.

Returns:



181
182
183
184
185
186
187
188
189
190
191
# File 'lib/cloud_events/json_format.rb', line 181

def decode_hash_structure structure, charset: nil, data_decoder: nil
  spec_version = structure["specversion"].to_s
  case spec_version
  when "0.3"
    decode_hash_structure_v0 structure, charset
  when /^1(\.|$)/
    decode_hash_structure_v1 structure, charset, spec_version, data_decoder
  else
    raise SpecVersionError, "Unrecognized specversion: #{spec_version}"
  end
end

#encode_data(spec_version: nil, data: UNSPECIFIED, content_type: nil, sort: false, **_other_kwargs) ⇒ Hash?

Encode an event data object to a JSON formatted string. See Format#encode_data for a general description.

Expects :spec_version, :data and :content_type arguments, and will decline the request unless all three are provided. The :data object can be any Ruby object that can be interpreted as JSON. Most Ruby objects will work, but normally it will be a JSON value type comprising hashes, arrays, strings, numbers, booleans, or nil.

If decoding succeeded, returns a hash with the following keys:

  • :content (String) The serialized form of the data.
  • :content_type (ContentType) The content type for the output.

Parameters:

  • data (Object) (defaults to: UNSPECIFIED)

    A data object to encode.

  • content_type (CloudEvents::ContentType) (defaults to: nil)

    The input content type

  • sort (boolean) (defaults to: false)

    Whether to sort keys of the JSON output.

Returns:

  • (Hash)

    if accepting the request.

  • (nil)

    if declining the request.



158
159
160
161
162
163
164
165
166
167
168
# File 'lib/cloud_events/json_format.rb', line 158

def encode_data spec_version: nil, data: UNSPECIFIED, content_type: nil, sort: false, **_other_kwargs
  return nil unless spec_version
  return nil if data == UNSPECIFIED
  return nil unless json_content_type? content_type
  unless spec_version =~ /^0\.3|1(\.|$)/
    raise SpecVersionError, "Unrecognized specversion: #{spec_version}"
  end
  data = sort_keys data if sort
  content = ::JSON.dump data
  { content: content, content_type: content_type }
end

#encode_event(event: nil, event_batch: nil, data_encoder: nil, sort: false, **_other_kwargs) ⇒ Hash?

Encode an event or batch to a JSON string. This formatter should be able to handle any event. See Format#decode_event for a general description.

Expects either the :event or the :event_batch argument, but not both, and will decline the request unless exactly one is provided.

If encoding succeeded, returns a hash with the following keys:

  • :content (String) The serialized form of the event or batch.
  • :content_type (ContentType) The content type for the output.

Parameters:

  • event (CloudEvents::Event) (defaults to: nil)

    An event to encode.

  • event_batch (Array<CloudEvents::Event>) (defaults to: nil)

    An event batch to encode.

  • data_encoder (#encode_data) (defaults to: nil)

    Optional data field encoder, used for non-JSON content types.

  • sort (boolean) (defaults to: false)

    Whether to sort keys of the JSON output.

Returns:

  • (Hash)

    if accepting the request.

  • (nil)

    if declining the request.

Raises:



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/cloud_events/json_format.rb', line 81

def encode_event event: nil, event_batch: nil, data_encoder: nil, sort: false, **_other_kwargs
  if event && !event_batch
    structure = encode_hash_structure event, data_encoder: data_encoder
    structure = sort_keys structure if sort
    subtype = "cloudevents"
  elsif event_batch && !event
    structure = event_batch.map do |elem|
      structure_elem = encode_hash_structure elem, data_encoder: data_encoder
      sort ? sort_keys(structure_elem) : structure_elem
    end
    subtype = "cloudevents-batch"
  else
    return nil
  end
  content = ::JSON.dump structure
  content_type = ContentType.new "application/#{subtype}+json; charset=#{charset_of content}"
  { content: content, content_type: content_type }
rescue ::JSON::JSONError
  raise FormatSyntaxError, "JSON syntax error"
end

#encode_hash_structure(event, data_encoder: nil) ⇒ String

Encode a single event to a hash data structure with keys and types conforming to the JSON envelope.

Parameters:

  • event (CloudEvents::Event)

    An input event.

  • data_encoder (#encode_data) (defaults to: nil)

    Optional data field encoder, used for non-JSON content types.

Returns:

  • (String)

    The hash structure.



202
203
204
205
206
207
208
209
210
211
# File 'lib/cloud_events/json_format.rb', line 202

def encode_hash_structure event, data_encoder: nil
  case event
  when Event::V0
    encode_hash_structure_v0 event
  when Event::V1
    encode_hash_structure_v1 event, data_encoder
  else
    raise SpecVersionError, "Unrecognized event type: #{event.class}"
  end
end