diff --git a/ext/cbson/cbson.c b/ext/cbson/cbson.c index ede11e5..0a75da6 100644 --- a/ext/cbson/cbson.c +++ b/ext/cbson/cbson.c @@ -289,7 +289,18 @@ static void write_doc(bson_buffer* buffer, VALUE hash) { int start_position = buffer->position; int length_location = buffer_save_bytes(buffer, 4); - rb_hash_foreach(hash, write_element, (VALUE)buffer); + // we have to check for an OrderedHash and handle that specially + if (strcmp(rb_class2name(RBASIC(hash)->klass), "OrderedHash") == 0) { + VALUE keys = rb_funcall(hash, rb_intern("keys"), 0); + int i; + for(i = 0; i < RARRAY(keys)->len; i++) { + VALUE key = RARRAY(keys)->ptr[i]; + VALUE value = rb_hash_aref(hash, key); + write_element(key, value, (VALUE)buffer); + } + } else { + rb_hash_foreach(hash, write_element, (VALUE)buffer); + } // write null byte and fill in length buffer_write_bytes(buffer, &zero, 1); diff --git a/tests/test_bson.rb b/tests/test_bson.rb index 0e362bb..4539851 100644 --- a/tests/test_bson.rb +++ b/tests/test_bson.rb @@ -1,5 +1,6 @@ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') require 'mongo' +require 'mongo/util/ordered_hash' require 'test/unit' class BSONTest < Test::Unit::TestCase @@ -37,6 +38,16 @@ class BSONTest < Test::Unit::TestCase assert_equal doc, @b.deserialize end + def test_ordered_hash + doc = OrderedHash.new + doc["b"] = 1 + doc["a"] = 2 + doc["c"] = 3 + doc["d"] = 4 + @b.serialize(doc) + assert_equal doc, @b.deserialize + end + def test_object doc = {'doc' => {'age' => 42, 'name' => 'Spongebob', 'shoe_size' => 9.5}} @b.serialize(doc)