struct BSON

Overview

BSON is a binary format in which zero or more ordered key/value pairs are stored as a single entity.

BSON [bee · sahn], short for Bin­ary JSON, is a bin­ary-en­coded seri­al­iz­a­tion of JSON-like doc­u­ments. Like JSON, BSON sup­ports the em­bed­ding of doc­u­ments and ar­rays with­in oth­er doc­u­ments and ar­rays. BSON also con­tains ex­ten­sions that al­low rep­res­ent­a­tion of data types that are not part of the JSON spec. For ex­ample, BSON has a Date type and a BinData type.

See: http://bsonspec.org/

require "bson"

data = BSON.new({
  hello: "world",
  time:  Time.utc,
  name:  BSON.new({
    first_name: "John",
    last_name:  "Doe",
  }),
  fruits: ["Orange", "Banana"],
})

puts data.to_json
# => {"hello":"world","time":{"$date":"2020-05-18T07:32:13.621000000Z"},"name":{"first_name":"John","last_name":"Doe"},"fruits":["Orange","Banana"]}

Included Modules

Defined in:

Constructors

Class Method Summary

Instance Method Summary

Constructor Detail

def self.new(data : Bytes? = nil, validate? = false) #

Allocate a BSON instance from a byte array.

NOTE The byte array is cloned.

data = "160000000378000E0000000261000200000062000000".hexbytes
io = IO::Memory.new(data)
bson = BSON.new(io)
puts bson.to_json # => {"x":{"a":"b"}}

def self.new(io : IO) #

Allocate a BSON instance from an IO

data = "160000000378000E0000000261000200000062000000".hexbytes
bson = BSON.new(data)
puts bson.to_json # => {"x":{"a":"b"}}

def self.new(tuple : NamedTuple) #

Allocate a BSON instance from a NamedTuple.

puts BSON.new({
  hello: "world",
}).to_json # => {"hello":"world"}

def self.new(h : Hash) #

Allocate a BSON instance from a Hash.

puts BSON.new({
  "hello" => "world",
}).to_json # => {"hello":"world"}

def self.new(bson : BSON) #

No-op


def self.new(ary : Array) #

Allocate a BSON instance from an Array.

puts BSON.new([1, 2, 3]).to_json # => [1,2,3]

def self.new(serializable : BSON::Serializable) #

Allocate a BSON instance from an instance of BSON::Serializable.


Class Method Detail

def self.from_json(json : String) #

Allocate a BSON instance from a relaxed extended json representation.

NOTE see https://github.com/mongodb/specifications/blob/master/source/extended-json.rst

bson = BSON.from_json(%({
  "_id": {
    "$oid": "57e193d7a9cc81b4027498b5"
  },
  "String": "string",
  "Int": 42,
  "Double": -1.0
}))
puts bson.to_json # => {"_id":{"$oid":"57e193d7a9cc81b4027498b5"},"String":"string","Int":42,"Double":-1.0}

Instance Method Detail

def <=>(other : BSON) #

Compare with another BSON value.

puts BSON.new({a: 1}) <=> BSON.new({a: 1}) # => 0
puts BSON.new({a: 1}) <=> BSON.new({b: 2}) # => -1

def [](key : String | ::Symbol) : Value #

Return the element with the given key.

NOTE Will raise if the key is not found.

bson = BSON.new({ key: "value" })
puts bson["key"] # =>"value"
puts bson["nope"] # => Unhandled exception: Missing bson key: nope (Exception)

def []=(key : String | ::Symbol, value) #

Append a key/value pair.

bson = BSON.new
bson["key"] = "value"
puts bson.to_json # => {"key":"value"}

def []?(key : String | ::Symbol) : Value? #

Return the element with the given key, or nil if the key is not present.

bson = BSON.new({key: "value"})
puts bson["key"]?  # => "value"
puts bson["nope"]? # => nil

def append(other : BSON) #

Append the contents of another BSON instance.

bson = BSON.new
other_bson = BSON.new({key: "value", key2: "value2"})
bson.append(other_bson)
puts bson.to_json # => {"key":"value","key2":"value2"}

def append(**args) #

Append one or more key/value pairs.

NOTE more efficient for appending multiple values than calling #[]= individually.

bson = BSON.new
bson.append(key: "value", key2: "value2")
puts bson.to_json # => {"key":"value","key2":"value2"}

def clear #

Clears the BSON instance.


def data : Slice(UInt8) #

Underlying bytes


def each #

Returns an Iterator over each key/value pair.


def each(&block : Item -> _) #

Yield each key/value pair to the block.

NOTE Underlying BSON code as well as the binary subtype are also yielded to the block as additional arguments.

BSON.new({
  a: 1,
  b: "2",
  c: Slice[0_u8, 1_u8, 2_u8],
}).each { |(key, value, code, binary_subtype)|
  puts "#{key} => #{value}, code: #{code}, subtype: #{binary_subtype}"
# a => 1, code: Int32, subtype:
# b => 2, code: String, subtype:
# c => Bytes[0, 1, 2], code: Binary, subtype: Generic
}

def empty? : Bool #

Returns true if the BSON is empty.


def has_key?(key : String | ::Symbol) : Bool #

Returns true when key given by key exists, otherwise false.


def size #

Return the size of the BSON instance in bytes.


def to_canonical_extjson #

Serialize this BSON instance into a canonical extended json representation.

NOTE see https://github.com/mongodb/specifications/blob/master/source/extended-json.rst

bson = BSON.from_json(%({
  "Int": 42,
  "Double": -1.0
}))
puts bson.to_canonical_extjson # => {"Int":{"$numberLong":"42"},"Double":{"$numberDouble":"-1.0"}}

def to_h #

Returns a Hash representation.

NOTE This function is recursive and will convert nested BSON to hash objects.

bson = BSON.new({
  a: 1,
  b: "2",
  c: {
    d: 1,
  },
})
pp bson.to_h # => {"a" => 1, "b" => "2", "c" => { "d" => 1}}

def to_json(builder : JSON::Builder, *, array = false) #

ameba:disable Metrics/CyclomaticComplexity


def validate! #

Validate that the BSON is well-formed.

bson = BSON.new("140000000461000D0000001030000A0000000000".hexbytes)
bson.validate!
# => Unhandled exception: Invalid BSON (overflow) (Exception)