diff --git a/compiler2/Value.cc b/compiler2/Value.cc
index bc61a5b4f2ead17b6439713d8a3ab7406d06f5f2..fa470b3e209ecf234178f872f54beb81ed7c92b6 100644
--- a/compiler2/Value.cc
+++ b/compiler2/Value.cc
@@ -183,6 +183,7 @@ namespace Common {
       case OPTYPE_BIT2INT:
       case OPTYPE_BIT2OCT:
       case OPTYPE_BIT2STR:
+      case OPTYPE_BSON2JSON:
       case OPTYPE_CBOR2JSON:
       case OPTYPE_CHAR2INT:
       case OPTYPE_CHAR2OCT:
@@ -196,6 +197,7 @@ namespace Common {
       case OPTYPE_INT2FLOAT:
       case OPTYPE_INT2STR:
       case OPTYPE_INT2UNICHAR:
+      case OPTYPE_JSON2BSON:
       case OPTYPE_JSON2CBOR:
       case OPTYPE_OCT2BIT:
       case OPTYPE_OCT2CHAR:
@@ -534,6 +536,7 @@ namespace Common {
     case OPTYPE_BIT2INT:
     case OPTYPE_BIT2OCT:
     case OPTYPE_BIT2STR:
+    case OPTYPE_BSON2JSON:
     case OPTYPE_CBOR2JSON:
     case OPTYPE_CHAR2INT:
     case OPTYPE_CHAR2OCT:
@@ -547,6 +550,7 @@ namespace Common {
     case OPTYPE_INT2FLOAT:
     case OPTYPE_INT2STR:
     case OPTYPE_INT2UNICHAR:
+    case OPTYPE_JSON2BSON:
     case OPTYPE_JSON2CBOR:
     case OPTYPE_OCT2BIT:
     case OPTYPE_OCT2CHAR:
@@ -939,6 +943,7 @@ namespace Common {
     case OPTYPE_BIT2INT:
     case OPTYPE_BIT2OCT:
     case OPTYPE_BIT2STR:
+    case OPTYPE_BSON2JSON:
     case OPTYPE_CBOR2JSON:
     case OPTYPE_CHAR2INT:
     case OPTYPE_CHAR2OCT:
@@ -952,6 +957,7 @@ namespace Common {
     case OPTYPE_INT2FLOAT:
     case OPTYPE_INT2STR:
     case OPTYPE_INT2UNICHAR:
+    case OPTYPE_JSON2BSON:
     case OPTYPE_JSON2CBOR:
     case OPTYPE_OCT2BIT:
     case OPTYPE_OCT2CHAR:
@@ -1726,6 +1732,7 @@ namespace Common {
     case OPTYPE_BIT2INT:
     case OPTYPE_BIT2OCT:
     case OPTYPE_BIT2STR:
+    case OPTYPE_BSON2JSON:
     case OPTYPE_CBOR2JSON:
     case OPTYPE_CHAR2INT:
     case OPTYPE_CHAR2OCT:
@@ -1739,6 +1746,7 @@ namespace Common {
     case OPTYPE_INT2FLOAT:
     case OPTYPE_INT2STR:
     case OPTYPE_INT2UNICHAR:
+    case OPTYPE_JSON2BSON:
     case OPTYPE_JSON2CBOR:
     case OPTYPE_OCT2BIT:
     case OPTYPE_OCT2CHAR:
@@ -1973,6 +1981,7 @@ namespace Common {
     case OPTYPE_BIT2INT:
     case OPTYPE_BIT2OCT:
     case OPTYPE_BIT2STR:
+    case OPTYPE_BSON2JSON:
     case OPTYPE_CBOR2JSON:
     case OPTYPE_CHAR2INT:
     case OPTYPE_CHAR2OCT:
@@ -1986,6 +1995,7 @@ namespace Common {
     case OPTYPE_INT2FLOAT:
     case OPTYPE_INT2STR:
     case OPTYPE_INT2UNICHAR:
+    case OPTYPE_JSON2BSON:
     case OPTYPE_JSON2CBOR:
     case OPTYPE_OCT2BIT:
     case OPTYPE_OCT2CHAR:
@@ -2342,6 +2352,7 @@ namespace Common {
       case OPTYPE_BIT2INT:
       case OPTYPE_BIT2OCT:
       case OPTYPE_BIT2STR:
+      case OPTYPE_BSON2JSON:
       case OPTYPE_CBOR2JSON:
       case OPTYPE_CHAR2INT:
       case OPTYPE_CHAR2OCT:
@@ -2355,6 +2366,7 @@ namespace Common {
       case OPTYPE_INT2FLOAT:
       case OPTYPE_INT2STR:
       case OPTYPE_INT2UNICHAR:
+      case OPTYPE_JSON2BSON:
       case OPTYPE_JSON2CBOR:
       case OPTYPE_OCT2BIT:
       case OPTYPE_OCT2CHAR:
@@ -3536,6 +3548,7 @@ namespace Common {
       case OPTYPE_OCT2UNICHAR:
       case OPTYPE_ENCVALUE_UNICHAR:
       case OPTYPE_ANY2UNISTR:
+      case OPTYPE_BSON2JSON:
       case OPTYPE_CBOR2JSON:
         return Type::T_USTR;
       case OPTYPE_INT2BIT:
@@ -3550,6 +3563,7 @@ namespace Common {
       case OPTYPE_STR2HEX:
         return Type::T_HSTR;
       case OPTYPE_INT2OCT:
+      case OPTYPE_JSON2BSON:
       case OPTYPE_JSON2CBOR:
       case OPTYPE_CHAR2OCT:
       case OPTYPE_HEX2OCT:
@@ -3826,6 +3840,8 @@ namespace Common {
       return "bit2oct()";
     case OPTYPE_BIT2STR:
       return "bit2str()";
+    case OPTYPE_BSON2JSON:
+      return "bson2json()";
     case OPTYPE_CBOR2JSON:
       return "cbor2json()";
     case OPTYPE_CHAR2INT:
@@ -3852,6 +3868,8 @@ namespace Common {
       return "int2str()";
     case OPTYPE_INT2UNICHAR:
       return "int2unichar()";
+    case OPTYPE_JSON2BSON:
+      return "json2bson()";
     case OPTYPE_JSON2CBOR:
       return "json2cbor()";
     case OPTYPE_OCT2BIT:
@@ -6994,6 +7012,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
       }
       break;
     case OPTYPE_OCT2BIT:
+    case OPTYPE_BSON2JSON:
     case OPTYPE_CBOR2JSON:
     case OPTYPE_OCT2HEX:
     case OPTYPE_OCT2STR:
@@ -7111,6 +7130,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
         chk_expr_eval_value(v1, t_chk, refch, exp_val);
       }
       break;
+    case OPTYPE_JSON2BSON:
     case OPTYPE_JSON2CBOR: // v1
       v1=u.expr.v1;
       {
@@ -7859,6 +7879,8 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
     case OPTYPE_ISTEMPLATEKIND: // ti1 v2
     case OPTYPE_CBOR2JSON: // v1
     case OPTYPE_JSON2CBOR: // v1
+    case OPTYPE_BSON2JSON: // v1
+    case OPTYPE_JSON2BSON: // v1
       break;
     case OPTYPE_TESTCASENAME: { // -
       if (!my_scope) FATAL_ERROR("Value::evaluate_value()");
@@ -9163,6 +9185,8 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
       case OPTYPE_ISTEMPLATEKIND: // ti1 v2
       case OPTYPE_CBOR2JSON:
       case OPTYPE_JSON2CBOR:
+      case OPTYPE_BSON2JSON:
+      case OPTYPE_JSON2BSON:
         return true;
       case OPTYPE_COMP_NULL: // -
         return false;
@@ -10396,6 +10420,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
     case OPTYPE_BIT2INT:
     case OPTYPE_BIT2OCT:
     case OPTYPE_BIT2STR:
+    case OPTYPE_BSON2JSON:
     case OPTYPE_CBOR2JSON:
     case OPTYPE_CHAR2INT:
     case OPTYPE_CHAR2OCT:
@@ -10409,6 +10434,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
     case OPTYPE_INT2FLOAT:
     case OPTYPE_INT2STR:
     case OPTYPE_INT2UNICHAR:
+    case OPTYPE_JSON2BSON:
     case OPTYPE_JSON2CBOR:
     case OPTYPE_OCT2BIT:
     case OPTYPE_OCT2CHAR:
@@ -10808,6 +10834,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
     case OPTYPE_BIT2INT: // v1
     case OPTYPE_BIT2OCT: // v1
     case OPTYPE_BIT2STR: // v1
+    case OPTYPE_BSON2JSON: // v1
     case OPTYPE_CBOR2JSON: // v1
     case OPTYPE_CHAR2INT: // v1
     case OPTYPE_CHAR2OCT: // v1
@@ -10821,6 +10848,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
     case OPTYPE_INT2FLOAT: // v1
     case OPTYPE_INT2STR: // v1
     case OPTYPE_INT2UNICHAR: // v1
+    case OPTYPE_JSON2BSON: // v1
     case OPTYPE_JSON2CBOR: // v1
     case OPTYPE_OCT2BIT: // v1
     case OPTYPE_OCT2CHAR: // v1
@@ -11212,6 +11240,8 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
         return create_stringRepr_predef1("bit2oct");
       case OPTYPE_BIT2STR:
         return create_stringRepr_predef1("bit2str");
+      case OPTYPE_BSON2JSON:
+        return create_stringRepr_predef1("bson2json");
       case OPTYPE_CBOR2JSON:
         return create_stringRepr_predef1("cbor2json");
       case OPTYPE_CHAR2INT:
@@ -11236,6 +11266,8 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
         return create_stringRepr_predef1("int2float");
       case OPTYPE_INT2STR:
         return create_stringRepr_predef1("int2str");
+      case OPTYPE_JSON2BSON:
+        return create_stringRepr_predef1("json2bson");
       case OPTYPE_JSON2CBOR:
         return create_stringRepr_predef1("json2cbor");
       case OPTYPE_INT2UNICHAR:
@@ -12211,6 +12243,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
       case OPTYPE_BIT2INT:
       case OPTYPE_BIT2OCT:
       case OPTYPE_BIT2STR:
+      case OPTYPE_BSON2JSON:
       case OPTYPE_CBOR2JSON:
       case OPTYPE_CHAR2INT:
       case OPTYPE_CHAR2OCT:
@@ -12224,6 +12257,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
       case OPTYPE_INT2FLOAT:
       case OPTYPE_INT2STR:
       case OPTYPE_INT2UNICHAR:
+      case OPTYPE_JSON2BSON:
       case OPTYPE_JSON2CBOR:
       case OPTYPE_OCT2BIT:
       case OPTYPE_OCT2CHAR:
@@ -12518,6 +12552,9 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
     case OPTYPE_BIT2STR:
       generate_code_expr_predef1(expr, "bit2str", u.expr.v1);
       break;
+    case OPTYPE_BSON2JSON:
+      generate_code_expr_predef1(expr, "bson2json", u.expr.v1);
+      break;  
     case OPTYPE_CBOR2JSON:
       generate_code_expr_predef1(expr, "cbor2json", u.expr.v1);
       break;  
@@ -12557,6 +12594,9 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
     case OPTYPE_INT2UNICHAR:
       generate_code_expr_predef1(expr, "int2unichar", u.expr.v1);
       break;
+     case OPTYPE_JSON2BSON:
+      generate_code_expr_predef1(expr, "json2bson", u.expr.v1);
+      break;  
     case OPTYPE_JSON2CBOR:
       generate_code_expr_predef1(expr, "json2cbor", u.expr.v1);
       break;  
@@ -14665,6 +14705,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
     case OPTYPE_BIT2INT:
     case OPTYPE_BIT2OCT:
     case OPTYPE_BIT2STR:
+    case OPTYPE_BSON2JSON:
     case OPTYPE_CBOR2JSON:
     case OPTYPE_CHAR2INT:
     case OPTYPE_CHAR2OCT:
@@ -14678,6 +14719,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
     case OPTYPE_INT2FLOAT:
     case OPTYPE_INT2STR:
     case OPTYPE_INT2UNICHAR:
+    case OPTYPE_JSON2BSON:
     case OPTYPE_JSON2CBOR:
     case OPTYPE_OCT2BIT:
     case OPTYPE_OCT2CHAR:
diff --git a/compiler2/Value.hh b/compiler2/Value.hh
index 33282982a28095e1ce69b5a3c03d203db1a39177..66e94f7ec05d3376ddd1079baea45083a12e4a02 100644
--- a/compiler2/Value.hh
+++ b/compiler2/Value.hh
@@ -275,6 +275,8 @@ namespace Common {
       
       OPTYPE_CBOR2JSON, // v1
       OPTYPE_JSON2CBOR, // v1
+      OPTYPE_BSON2JSON, // v1
+      OPTYPE_JSON2BSON, // v1
 
       NUMBER_OF_OPTYPES // must be last
     };
diff --git a/compiler2/ttcn3/compiler.l b/compiler2/ttcn3/compiler.l
index f97f5893b236bdc3f10d82b9b9b4e9be43be73f9..852036dddfb5b3adcd71353b96b01bde42278c61 100644
--- a/compiler2/ttcn3/compiler.l
+++ b/compiler2/ttcn3/compiler.l
@@ -540,6 +540,7 @@ bit2hex		RETURN(bit2hexKeyword);
 bit2int		RETURN(bit2intKeyword);
 bit2oct		RETURN(bit2octKeyword);
 bit2str		RETURN(bit2strKeyword);
+bson2json	RETURN(bson2JsonKeyword);
 cbor2json	RETURN(cbor2JsonKeyword);
 char2int	RETURN(char2intKeyword);
 char2oct	RETURN(char2octKeyword);
@@ -563,6 +564,7 @@ isbound		RETURN(isboundKeyword);
 ischosen	RETURN(ischosenKeyword);
 ispresent	RETURN(ispresentKeyword);
 istemplatekind  RETURN(istemplatekindKeyword);
+json2bson	RETURN(json2bsonKeyword);
 json2cbor	RETURN(json2CborKeyword);
 lengthof	RETURN(lengthofKeyword);
 oct2bit		RETURN(oct2bitKeyword);
diff --git a/compiler2/ttcn3/compiler.y b/compiler2/ttcn3/compiler.y
index 862c80520429499350c611d64dc2de37ba106866..675618d476df46927d5b474ae9911bdea39acefd 100644
--- a/compiler2/ttcn3/compiler.y
+++ b/compiler2/ttcn3/compiler.y
@@ -837,6 +837,7 @@ static const string anyname("anytype");
 %token bit2intKeyword
 %token bit2octKeyword
 %token bit2strKeyword
+%token bson2JsonKeyword
 %token cbor2JsonKeyword
 %token char2intKeyword
 %token char2octKeyword
@@ -859,6 +860,7 @@ static const string anyname("anytype");
 %token ischosenKeyword
 %token ispresentKeyword
 %token istemplatekindKeyword
+%token json2bsonKeyword
 %token json2CborKeyword
 %token lengthofKeyword
 %token oct2bitKeyword
@@ -9874,6 +9876,7 @@ PredefinedOpKeyword1:
 | bit2octKeyword { $$ = Value::OPTYPE_BIT2OCT; }
 | bit2strKeyword { $$ = Value::OPTYPE_BIT2STR; }
 | cbor2JsonKeyword { $$ = Value::OPTYPE_CBOR2JSON; }
+| bson2JsonKeyword { $$ = Value::OPTYPE_BSON2JSON; }
 | char2intKeyword { $$ = Value::OPTYPE_CHAR2INT; }
 | char2octKeyword { $$ = Value::OPTYPE_CHAR2OCT; }
 | float2intKeyword { $$ = Value::OPTYPE_FLOAT2INT; }
@@ -9887,6 +9890,7 @@ PredefinedOpKeyword1:
 | int2strKeyword { $$ = Value::OPTYPE_INT2STR; }
 | int2unicharKeyword { $$ = Value::OPTYPE_INT2UNICHAR; }
 | json2CborKeyword { $$ = Value::OPTYPE_JSON2CBOR; }
+| json2bsonKeyword { $$ = Value::OPTYPE_JSON2BSON; }
 | oct2bitKeyword { $$ = Value::OPTYPE_OCT2BIT; }
 | oct2charKeyword { $$ = Value::OPTYPE_OCT2CHAR; }
 | oct2hexKeyword { $$ = Value::OPTYPE_OCT2HEX; }
diff --git a/core/Addfunc.cc b/core/Addfunc.cc
index 4d72b8b1936b1ed7876a891cf3cb45f0553091f9..5b541276e428d597f85ddf0b83b124a3094010bc 100644
--- a/core/Addfunc.cc
+++ b/core/Addfunc.cc
@@ -3170,3 +3170,31 @@ UNIVERSAL_CHARSTRING cbor2json(const OCTETSTRING& value) {
   result.decode_utf8(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
   return result;
 }
+
+UNIVERSAL_CHARSTRING bson2json(const OCTETSTRING& value) {
+  UNIVERSAL_CHARSTRING result;
+  TTCN_Buffer buff;
+  buff.put_os(value);
+  JSON_Tokenizer tok;
+  bson2json_coding(buff, tok, false, false);
+  result.decode_utf8(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
+  return result;
+}
+
+OCTETSTRING json2bson(const UNIVERSAL_CHARSTRING& value) {
+  OCTETSTRING result;
+  TTCN_Buffer buff;
+  value.encode_utf8(buff);
+  const unsigned char* ustr = buff.get_data();
+  const size_t ustr_len = buff.get_len();
+  char* json_str = mcopystr((const char*)ustr);
+  JSON_Tokenizer tok(json_str, ustr_len);
+  Free(json_str);
+  buff.clear();
+  INTEGER length = 0;
+  CHARSTRING cs;
+  bool is_special;
+  json2bson_coding(buff, tok, false, false, length, cs, is_special);
+  buff.get_string(result);
+  return result;
+}
diff --git a/core/Addfunc.hh b/core/Addfunc.hh
index 11dc1a5805672e4b24cc7e8edb6c778385c5a759..04feabb154f307eff2f916b5c8e6adbeb4cf6c1b 100644
--- a/core/Addfunc.hh
+++ b/core/Addfunc.hh
@@ -488,4 +488,7 @@ extern OCTETSTRING decode_base64(const CHARSTRING& b64);
 extern OCTETSTRING json2cbor(const UNIVERSAL_CHARSTRING& value);
 extern UNIVERSAL_CHARSTRING cbor2json(const OCTETSTRING& value);
 
+extern OCTETSTRING json2bson(const UNIVERSAL_CHARSTRING& value);
+extern UNIVERSAL_CHARSTRING bson2json(const OCTETSTRING& value);
+
 #endif
diff --git a/core/JSON.cc b/core/JSON.cc
index 354da842f1674fd5a0c38d25b52a2998326bf46a..12e85c0cd0ae72965421b65b718d647032e83f26 100644
--- a/core/JSON.cc
+++ b/core/JSON.cc
@@ -84,6 +84,10 @@ const TTCN_JSONdescriptor_t ENUMERATED_json_ = { FALSE, NULL, FALSE, NULL, FALSE
 
 
 
+////////////////////////////////////////////////////////////////////////////////
+//// CBOR conversion
+////////////////////////////////////////////////////////////////////////////////
+
 // Never use buff.get_read_data() without checking if it has enough bytes in the
 // buffer.
 const unsigned char* check_and_get_buffer(const TTCN_Buffer& buff, int bytes) {
@@ -563,3 +567,944 @@ void cbor2json_coding(TTCN_Buffer& buff, JSON_Tokenizer& tok, bool in_object) {
       TTCN_error("Unexpected major type %i while decoding using cbor2json().", major_type);
   }
 }
+
+
+////////////////////////////////////////////////////////////////////////////////
+////  BSON conversion
+////////////////////////////////////////////////////////////////////////////////
+
+const TTCN_RAWdescriptor_t bson_float_raw_ = {64,SG_NO,ORDER_MSB,ORDER_LSB,ORDER_LSB,ORDER_LSB,EXT_BIT_NO,ORDER_LSB,ORDER_LSB,TOP_BIT_INHERITED,0,0,0,8,0,NULL,-1,CharCoding::UNKNOWN};
+const TTCN_Typedescriptor_t bson_float_descr_ = { NULL, NULL, &bson_float_raw_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+
+// Never use buff.get_read_data() without checking if it has enough bytes in the
+// buffer.
+const unsigned char* check_and_get_buffer_bson(const TTCN_Buffer& buff, int bytes) {
+  if (bytes < 0) {
+    TTCN_error("Incorrect length byte received: %d, while decoding using bson2json()", bytes);
+  }
+  if (buff.get_pos() + bytes > buff.get_len()) {
+    TTCN_error("Not enough bytes in bytestream while decoding using bson2json().");
+  }
+  return buff.get_read_data();
+}
+
+void encode_int_bson(TTCN_Buffer& buff, const INTEGER& int_num, INTEGER& length) {
+  if (int_num.is_native()) { // 32 bit
+    length = length + 4;
+    RInt value = (int)int_num;
+    for (size_t i = 0; i < 4; i++) {
+      buff.put_c(static_cast<unsigned char>(value >> i*8));
+    }
+  } else {
+    BIGNUM* bn = BN_dup(int_num.get_val().get_val_openssl());
+    INTEGER bn_length = BN_num_bytes(bn);
+    BN_free(bn);
+    long long int long_int = 0;
+    int bytes = 0;
+    if (bn_length <= 4) { // 32 bit
+      bytes = 4;
+      long_int = int_num.get_long_long_val();
+    } else if (bn_length <= 8) { //64 bit
+      bytes = 8;
+      long_int = int_num.get_long_long_val();
+    } else {
+      // The standard encodes max 64 bits
+      TTCN_error("An integer value which cannot be represented "
+                 "on 64bits cannot be encoded using json2bson()");
+    }
+    for (int i = 0; i < bytes; i++) {
+      buff.put_c(static_cast<unsigned char>(long_int >> i*8));
+    }
+    length = length + bytes;
+  }
+}
+
+INTEGER decode_int_bson(TTCN_Buffer& buff, int bytes) {
+  const unsigned char* uc = check_and_get_buffer_bson(buff, bytes);
+  buff.increase_pos(bytes);
+  if (bytes <= 4) { //32 bit
+    RInt value = 0;
+    for (size_t i = 0; i < 4; i++) {
+      value += uc[i] << i*8;
+    }
+    return INTEGER(value);
+  } else if (bytes <= 8) {
+    TTCN_Buffer tmp_buf;
+    for (int i = 0; i < bytes; i++) {
+      tmp_buf.put_c(uc[bytes-i-1]);
+    }
+    OCTETSTRING os;
+    tmp_buf.get_string(os);
+    INTEGER value = oct2int(os);
+    return value;
+  } else {
+    TTCN_error("An integer value larger than "
+               "64 bytes cannot be decoded using bson2json()");
+  }
+}
+
+void put_name(TTCN_Buffer& buff, INTEGER& length, CHARSTRING& name, bool in_array) {
+  if (in_array) {
+    buff.put_cs(name);
+    buff.put_c(0); // Closing 0
+    length = length + name.lengthof() + 1;
+    // TODO: is it very slow?
+    // Increment index
+    INTEGER num = str2int(name);
+    num = num + 1;
+    name = int2str(num);
+  } else {
+    buff.put_cs(name);
+    buff.put_c(0); // Closing 0
+    length = length + name.lengthof() + 1;
+  }
+}
+
+void get_name(TTCN_Buffer& buff, JSON_Tokenizer& tok, bool in_array) {
+  const unsigned char* uc = buff.get_read_data();
+  // Copy until closing 0
+  char* tmp_str = mcopystr(reinterpret_cast<const char*>(uc));
+  if (in_array == false) { // We dont need name when in array
+    tok.put_next_token(JSON_TOKEN_NAME, tmp_str);
+  }
+  buff.increase_pos(strlen(tmp_str)+1);
+  Free(tmp_str);
+}
+
+bool encode_bson_binary(TTCN_Buffer& buff, JSON_Tokenizer& tok, INTEGER& length) {
+  char *content;
+  size_t len;
+  json_token_t token;
+  // Check if this is really binary
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_STRING) {
+    return false;
+  }
+  CHARSTRING cs2(len-2, content+1);
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_NAME) {
+    return false;
+  }
+  CHARSTRING cs3(len, content);
+  if (cs3 != "$type") {
+    return false;
+  }
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_STRING) {
+    return false;
+  }
+  CHARSTRING cs4(len-2, content+1);
+  if (cs4.lengthof() != 2) {
+    return false;
+  }
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+  
+  buff.put_c(5);
+  length = length + 1;
+  // We do not know the name here. It will be inserted later.
+  OCTETSTRING os = decode_base64(cs2);
+  INTEGER os_len = os.lengthof();
+  encode_int_bson(buff, os_len, length);
+  unsigned int type = 0;
+  if (sscanf((const char*)cs4, "%02x", &type) != 1) {
+    TTCN_error("Incorrect binary format while encoding with json2bson()");
+  }
+  buff.put_c(type);
+  length = length + 1;
+  buff.put_os(os);
+  length = length + os_len;
+  return true;
+}
+
+bool encode_bson_date(TTCN_Buffer& buff, JSON_Tokenizer& tok, INTEGER& length) {
+  char *content;
+  size_t len;
+  json_token_t token;
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_START) {
+    return false;
+  }
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_NAME) {
+    return false;
+  }
+  CHARSTRING cs(len, content);
+  if (cs != "$numberLong") {
+    return false;
+  }
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_NUMBER) {
+    return false;
+  }
+  CHARSTRING cs2(len, content);
+  
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+  
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+  INTEGER int_num = str2int(cs2);
+  buff.put_c(9); // datetime
+  length = length + 1;
+  // We do not know the name here. It will be inserted later.
+  // Encode on 64 bit
+  long long int long_int = int_num.get_long_long_val();
+  for (int i = 0; i < 8; i++) {
+    buff.put_c(static_cast<unsigned char>(long_int >> i*8));
+  }
+  length = length + 8;
+  return true;
+}
+  
+
+bool encode_bson_timestamp(TTCN_Buffer& buff, JSON_Tokenizer& tok, INTEGER& length) {
+  char *content;
+  size_t len;
+  json_token_t token;
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_START) {
+    return false;
+  }
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_NAME) {
+    return false;
+  }
+  CHARSTRING cs(len, content);
+  if (cs != "t") {
+    return false;
+  }
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_NUMBER) {
+    return false;
+  }
+  CHARSTRING cs2(len, content);
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_NAME) {
+    return false;
+  }
+  CHARSTRING cs3(len, content);
+  if (cs3 != "i") {
+    return false;
+  }
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_NUMBER) {
+    return false;
+  }
+  CHARSTRING cs4(len, content);
+  
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+  INTEGER timestamp = str2int(cs2);
+  INTEGER increment = str2int(cs4);
+  buff.put_c(17);
+  length = length + 1;
+  // We do not know the name here. It will be inserted later.
+  encode_int_bson(buff, increment, length);
+  encode_int_bson(buff, timestamp, length);
+  return true;
+}
+
+bool encode_bson_regex(TTCN_Buffer& buff, JSON_Tokenizer& tok, INTEGER& length) {
+  char *content;
+  size_t len;
+  json_token_t token;
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_STRING) {
+    return false;
+  }
+  CHARSTRING regex(len-2, content+1);
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_NAME) {
+    return false;
+  }
+  CHARSTRING cs2(len, content);
+  if (cs2 != "$options") {
+    return false;
+  }
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_STRING) {
+    return false;
+  }
+  CHARSTRING options(len-2, content+1);
+  
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+  
+  buff.put_c(11);
+  length = length + 1;
+  // We do not know the name here. It will be inserted later.
+  buff.put_cs(regex);
+  length = length + regex.lengthof();
+  buff.put_c(0); // Closing 0
+  length = length + 1;
+  buff.put_cs(options);
+  length = length + options.lengthof();
+  buff.put_c(0); // Closing 0
+  length = length + 1;
+  return true;
+}
+
+bool encode_bson_oid(TTCN_Buffer& buff, JSON_Tokenizer& tok, INTEGER& length) {
+  char *content;
+  size_t len;
+  json_token_t token;
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_STRING) {
+    return false;
+  }
+  CHARSTRING id(len-2, content+1);
+  if (id.lengthof() != 24) {
+    return false;
+  }
+  
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+  
+  buff.put_c(7);
+  length = length + 1;
+  // We do not know the name here. It will be inserted later.
+  unsigned char hex[12];
+  for (size_t i = 0; i < 24; i = i + 2) {
+    if (sscanf(((const char*)id)+i, "%02x", (unsigned int*)&(hex[i/2])) != 1) {
+      TTCN_error("Incorrect binary format while encoding with json2bson()");
+    }
+  }
+  buff.put_s(12, hex);
+  length = length + 12;
+  return true;
+}
+
+bool encode_bson_ref(TTCN_Buffer& buff, JSON_Tokenizer& tok, INTEGER& length) {
+  char *content;
+  size_t len;
+  json_token_t token;
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_STRING) {
+    return false;
+  }
+  CHARSTRING name(len-2, content+1);
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_NAME) {
+    return false;
+  }
+  CHARSTRING cs(len, content);
+  if (cs != "$id") {
+    return false;
+  }
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_STRING) {
+    return false;
+  }
+  CHARSTRING id(len-2, content+1);
+  if (id.lengthof() != 24) {
+    return false;
+  }
+  
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+
+  buff.put_c(12);
+  length = length + 1;
+  // We do not know the name here. It will be inserted later.
+  INTEGER name_length = name.lengthof()+1;
+  encode_int_bson(buff, name_length, length);
+  buff.put_cs(name);
+  buff.put_c(0); // Closing 0
+  length = length + name_length;
+  unsigned char hex[12];
+  for (size_t i = 0; i < 24; i = i + 2) {
+    if (sscanf(((const char*)id)+i, "%02x", (unsigned int*)&(hex[i/2])) != 1) {
+      TTCN_error("Incorrect binary format while encoding with json2bson()");
+    }
+  }
+  buff.put_s(12, hex);
+  length = length + 12;
+  return true;
+}
+
+bool encode_bson_undefined(TTCN_Buffer& buff, JSON_Tokenizer& tok, INTEGER& length) {
+  char *content;
+  size_t len;
+  json_token_t token;
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_LITERAL_TRUE) {
+    return false;
+  }
+  
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+  
+  buff.put_c(6);
+  length = length + 1;
+  // We do not know the name here. It will be inserted later.
+  return true;
+}
+
+bool encode_bson_minkey(TTCN_Buffer& buff, JSON_Tokenizer& tok, INTEGER& length) {
+  char *content;
+  size_t len;
+  json_token_t token;
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_NUMBER) {
+    return false;
+  }
+  CHARSTRING cs(len, content);
+  if (cs != "1") {
+    return false;
+  }
+  
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+  
+  buff.put_c(255);
+  length = length + 1;
+  // We do not know the name here. It will be inserted later.
+  return true;
+}
+
+bool encode_bson_maxkey(TTCN_Buffer& buff, JSON_Tokenizer& tok, INTEGER& length) {
+  char *content;
+  size_t len;
+  json_token_t token;
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_NUMBER) {
+    return false;
+  }
+  CHARSTRING cs(len, content);
+  if (cs != "1") {
+    return false;
+  }
+  
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+  
+  buff.put_c(127);
+  length = length + 1;
+  // We do not know the name here. It will be inserted later.
+  return true;
+}
+
+bool encode_bson_numberlong(TTCN_Buffer& buff, JSON_Tokenizer& tok, INTEGER& length) {
+  char *content;
+  size_t len;
+  json_token_t token;
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_STRING) {
+    return false;
+  }
+  CHARSTRING cs(len-2, content+1);
+  
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+  
+  buff.put_c(18);
+  length = length + 1;
+  // We do not know the name here. It will be inserted later.
+  INTEGER number = str2int(cs);
+  long long int value = number.get_long_long_val();
+  for (int i = 0; i < 8; i++) {
+    buff.put_c(static_cast<unsigned char>(value >> i*8));
+  }
+  length = length + 8;
+  return true;
+}
+
+bool encode_bson_code_with_scope(TTCN_Buffer& buff, JSON_Tokenizer& tok, INTEGER& length) {
+  char *content;
+  size_t len;
+  json_token_t token;
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_STRING) {
+    return false;
+  }
+  CHARSTRING cs(len-2, content+1);
+  
+  tok.get_next_token(&token, &content, &len);
+  if (token != JSON_TOKEN_NAME) {
+    return false;
+  }
+  CHARSTRING cs2(len, content);
+  if (cs2 != "$scope") {
+    return false;
+  }
+  
+  INTEGER code_w_scope_length = 0;
+  bool is_special = false;
+  CHARSTRING f_name;
+  TTCN_Buffer sub_buff;
+  json2bson_coding(sub_buff, tok, false, false, code_w_scope_length, f_name, is_special);
+  
+  tok.get_next_token(&token, NULL, NULL);
+  if (token != JSON_TOKEN_OBJECT_END) {
+    return false;
+  }
+  
+  buff.put_c(15);
+  length = length + 1;
+  // We do not know the name here. It will be inserted later.
+  code_w_scope_length = code_w_scope_length + cs.lengthof() + 4 + 1;
+  encode_int_bson(buff, code_w_scope_length, code_w_scope_length);
+  encode_int_bson(buff, cs.lengthof()+1, length);
+  buff.put_string(cs);
+  buff.put_c(0); // Closing 0
+  buff.put_buf(sub_buff);
+  length = length + code_w_scope_length - 4; // We added the length of cs twice
+  return true;
+}
+
+
+void json2bson_coding(TTCN_Buffer& buff, JSON_Tokenizer& tok, bool in_object,
+       bool in_array, INTEGER& length, CHARSTRING& obj_name, bool& is_special) {
+  json_token_t token;
+  char* content = NULL;
+  size_t len;
+  size_t prev_pos = tok.get_buf_pos();
+  tok.get_next_token(&token, &content, &len);
+  if (in_object == false && token != JSON_TOKEN_OBJECT_START) {
+    TTCN_error("Json document must be an object when encoding with json2bson()");
+  }
+  switch(token) {
+    case JSON_TOKEN_OBJECT_START: {
+      TTCN_Buffer sub_buff;
+      INTEGER sub_len = 0;
+      CHARSTRING subobj_name;
+      if (obj_name.is_bound()) {
+        subobj_name = obj_name;
+      }
+      while ((prev_pos = tok.get_buf_pos(), tok.get_next_token(&token, NULL, NULL))) {
+        if (token != JSON_TOKEN_OBJECT_END) {
+          tok.set_buf_pos(prev_pos);
+          json2bson_coding(sub_buff, tok, true, false, sub_len, subobj_name, is_special);
+          // We found a specially translated json
+          if (is_special) {
+            // The sub_buff contains the encoded bson except the obj_name.
+            // We put it in here after the first byte
+            TTCN_Buffer tmp_buff;
+            tmp_buff.put_c(*(sub_buff.get_data()));
+            put_name(tmp_buff, sub_len, subobj_name, in_array);
+            tmp_buff.put_s(sub_buff.get_len()-1, sub_buff.get_data()+1);
+            sub_buff = tmp_buff;
+            in_object = false;
+            break;
+          }
+        } else {
+          sub_buff.put_c(0);// Closing zero
+          sub_len = sub_len + 1;
+          break;
+        }
+      }
+      
+      if (in_object == true) {
+        TTCN_Buffer tmp_buff;
+        tmp_buff.put_c(3); // embedded document
+        length = length + 1;
+        put_name(tmp_buff, length, obj_name, in_array);
+        encode_int_bson(tmp_buff, sub_len, sub_len);
+        length = length + sub_len;
+        tmp_buff.put_buf(sub_buff);
+        sub_buff = tmp_buff;
+      } else if (is_special == false) {
+        length = length + sub_len;
+        encode_int_bson(buff, length, length);
+      } else {
+        length = length + sub_len;
+        is_special = false;
+      }
+      buff.put_buf(sub_buff);
+      break;
+    }
+    case JSON_TOKEN_OBJECT_END:
+      TTCN_error("Unexpected object end character while encoding using json2bson().");
+      break;
+    case JSON_TOKEN_NAME: {
+      CHARSTRING cs(len, content);
+      prev_pos = tok.get_buf_pos();
+      if (cs == "$binary") {
+        is_special = encode_bson_binary(buff, tok, length);
+      } else if (cs == "$date") {
+        is_special = encode_bson_date(buff, tok, length);
+      } else if (cs == "$timestamp") {
+        is_special = encode_bson_timestamp(buff, tok, length);
+      } else if (cs == "$regex") {
+        is_special = encode_bson_regex(buff, tok, length);
+      } else if (cs == "$oid") {
+        is_special = encode_bson_oid(buff, tok, length);
+      } else if (cs == "$ref") {
+        is_special = encode_bson_ref(buff, tok, length);
+      } else if (cs == "$undefined") {
+        is_special = encode_bson_undefined(buff, tok, length);
+      } else if (cs == "$minKey") {
+        is_special = encode_bson_minkey(buff, tok, length);
+      } else if (cs == "$maxKey") {
+        is_special = encode_bson_maxkey(buff, tok, length);
+      } else if (cs == "$numberLong") {
+        is_special = encode_bson_numberlong(buff, tok, length);
+      } else if (cs == "$code") {
+        is_special = encode_bson_code_with_scope(buff, tok, length);
+      } else {
+        obj_name = cs;
+      }
+      if (!is_special) {
+        tok.set_buf_pos(prev_pos);
+        obj_name = cs;
+      }
+      break; }
+    case JSON_TOKEN_STRING: {
+      buff.put_c(2); // string
+      length = length + 1;
+      put_name(buff, length, obj_name, in_array);
+      encode_int_bson(buff, len-1, length); // Remove "-s but add terminating null
+      char * tmp_str = mcopystrn(content+1, len-2); // Remove "-s
+      buff.put_string(tmp_str);
+      buff.put_c(0); // Closing 0
+      length = length + (int)len-1; // Remove "-s but add terminating null
+      Free(tmp_str);
+      break; }
+    case JSON_TOKEN_NUMBER: {
+      char *str = mcopystrn(content, len);
+      size_t curr_pos = tok.get_buf_pos();
+      tok.set_buf_pos(prev_pos);
+      bool is_float = false;
+      tok.check_for_number(&is_float);
+      tok.set_buf_pos(curr_pos);
+      if (is_float) {
+        buff.put_c(1); // 64bit float
+        put_name(buff, length, obj_name, in_array);
+        double d;
+        sscanf(str, "%lf", &d);
+        FLOAT f = d;
+        f.encode(bson_float_descr_, buff, TTCN_EncDec::CT_RAW);
+      } else {
+        INTEGER int_num = str2int(str);
+        if (int_num.is_native()) {
+          buff.put_c(16); //32bit integer
+          length = length + 1;
+        } else {
+          buff.put_c(18); // 64bit integer
+          length = length + 1;
+        }
+        put_name(buff, length, obj_name, in_array);
+        encode_int_bson(buff, int_num, length);
+      }
+      Free(str);
+      break; }
+    case JSON_TOKEN_LITERAL_FALSE: {
+      buff.put_c(8); // true or false
+      put_name(buff, length, obj_name, in_array);
+      buff.put_c(0); // false
+      break; }
+    case JSON_TOKEN_LITERAL_TRUE: {
+      buff.put_c(8); // true or false
+      put_name(buff, length, obj_name, in_array);
+      buff.put_c(1); // true
+      break; }
+    case JSON_TOKEN_LITERAL_NULL: {
+      buff.put_c(10); // null
+      put_name(buff, length, obj_name, in_array);
+      break; }
+    case JSON_TOKEN_ARRAY_START: {
+      buff.put_c(4); // array
+      length = length + 1;
+      put_name(buff, length, obj_name, in_array);
+      obj_name = "0"; // arrays are objects but the key is a number which increases
+      TTCN_Buffer sub_buff;
+      INTEGER sub_length = 0;
+      while ((prev_pos = tok.get_buf_pos(), tok.get_next_token(&token, NULL, NULL))) {
+        if (token != JSON_TOKEN_ARRAY_END) {
+          tok.set_buf_pos(prev_pos);
+          in_array = true;
+          json2bson_coding(sub_buff, tok, in_object, in_array, sub_length, obj_name, is_special);
+        } else {
+          sub_buff.put_c(0);// Closing zero
+          sub_length = sub_length + 1;
+          break;
+        }
+      }
+      encode_int_bson(buff, sub_length, sub_length);
+      length = length + sub_length;
+      buff.put_buf(sub_buff);
+      break; }
+    default:
+      TTCN_error("Unexpected json token %i, while encoding using json2bson().", token);
+  }
+}
+
+void bson2json_coding(TTCN_Buffer& buff, JSON_Tokenizer& tok, bool in_object, bool in_array) {
+  INTEGER length = 0;
+  // Beginning of the document
+  if (in_object == false) {
+    length = decode_int_bson(buff, 4);
+    // Check if the input is long enough
+    check_and_get_buffer_bson(buff, length-4);
+    tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+    while (*(check_and_get_buffer_bson(buff, 1)) != 0) {
+      bson2json_coding(buff, tok, true, in_array);
+    }
+    buff.increase_pos(1);
+    tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+  } else {
+    const unsigned char* type = check_and_get_buffer_bson(buff, 1);
+    buff.increase_pos(1);
+    // There is always a name
+    get_name(buff, tok, in_array);
+    switch(*type) {
+      case 0: // document end
+        TTCN_error("Unexpected document end character while decoding with bson2json()");
+        break;
+      case 1: { // 64bit float
+        FLOAT f;
+        check_and_get_buffer_bson(buff, 8);
+        f.decode(bson_float_descr_, buff, TTCN_EncDec::CT_RAW);
+        f.JSON_encode(bson_float_descr_, tok);
+        break;
+      }
+      case 13: // Javascript code. Decoded as string
+      case 14: // Symbol. Decoded as string
+      case 2: { // UTF8 string
+        INTEGER len = decode_int_bson(buff, 4);
+        // Get the value of the pair
+        const unsigned char* uc = check_and_get_buffer_bson(buff, (int)len);
+        char *tmp_str = mcopystrn(reinterpret_cast<const char*>(uc), (int)len);
+        buff.increase_pos((int)len);
+        char* tmp_str2 = mprintf("\"%s\"", tmp_str);
+        tok.put_next_token(JSON_TOKEN_STRING, tmp_str2);
+        Free(tmp_str2);
+        Free(tmp_str);
+        break; }
+      case 3: { // Embedded document
+        length = decode_int_bson(buff, 4);
+        // Check if the input is long enough
+        check_and_get_buffer_bson(buff, length-4);
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        while (*(check_and_get_buffer_bson(buff, 1)) != 0) { // error message while converting
+          bson2json_coding(buff, tok, in_object, false);
+        }
+        buff.increase_pos(1); // Skip the closing 0
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        break; }
+      case 4: { // array
+        length = decode_int_bson(buff, 4);
+        // Check if the input is long enough
+        check_and_get_buffer_bson(buff, length-4);
+        tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
+        in_array = true;
+        while (*(check_and_get_buffer_bson(buff, 1)) != 0) { // erorr message while converting
+          bson2json_coding(buff, tok, in_object, in_array);
+        }
+        buff.increase_pos(1); // Skip the closing 0
+        tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
+        break; }
+      case 5: { // bytestring
+        // decode bytestring length
+        INTEGER bytestr_length = decode_int_bson(buff, 4);
+        OCTETSTRING os(1, check_and_get_buffer_bson(buff, 1));
+        buff.increase_pos(1);
+        INTEGER typestr_type = oct2int(os);
+        char* str_type = mprintf("\"%02x\"", (int)typestr_type);
+        OCTETSTRING data(bytestr_length, check_and_get_buffer_bson(buff, bytestr_length));
+        buff.increase_pos(bytestr_length);
+        CHARSTRING cs = encode_base64(data);
+        char* data_str = mprintf("\"%s\"", (const char*)cs);
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        tok.put_next_token(JSON_TOKEN_NAME, "$binary");
+        tok.put_next_token(JSON_TOKEN_STRING, data_str);
+        tok.put_next_token(JSON_TOKEN_NAME, "$type");
+        tok.put_next_token(JSON_TOKEN_STRING, str_type);
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        Free(data_str);
+        Free(str_type);
+        break; }
+      case 6: { // undefined
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        tok.put_next_token(JSON_TOKEN_NAME, "$undefined");
+        tok.put_next_token(JSON_TOKEN_LITERAL_TRUE);
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        break; }
+      case 7: { // oid
+        OCTETSTRING os(12, check_and_get_buffer_bson(buff, 12));
+        char* tmp_oct = NULL;
+        for (size_t i = 0; i < 12; i++) {
+          tmp_oct = mputprintf(tmp_oct, "%02X", os[i].get_octet());
+        }
+        char *str_hex = mprintf("\"%s\"", tmp_oct);
+        buff.increase_pos(12);
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        tok.put_next_token(JSON_TOKEN_NAME, "$oid");
+        tok.put_next_token(JSON_TOKEN_STRING, str_hex);
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        Free(str_hex);
+        Free(tmp_oct);
+        break; }
+      case 8: {  // true or false
+        const unsigned char* uc = check_and_get_buffer_bson(buff, 1);
+        if (*uc == 0) {
+          tok.put_next_token(JSON_TOKEN_LITERAL_FALSE, NULL);
+        } else {
+          tok.put_next_token(JSON_TOKEN_LITERAL_TRUE, NULL);
+        }
+        buff.increase_pos(1);
+        break;
+      }
+      case 9: { // datetime
+        INTEGER date = decode_int_bson(buff, 8);
+        char *tmp_str = mprintf("%lld", date.get_long_long_val());
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        tok.put_next_token(JSON_TOKEN_NAME, "$date");
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        tok.put_next_token(JSON_TOKEN_NAME, "$numberLong");
+        tok.put_next_token(JSON_TOKEN_NUMBER, tmp_str);
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        Free(tmp_str);
+        break; }
+      case 10: { // null
+        tok.put_next_token(JSON_TOKEN_LITERAL_NULL, NULL);
+        break;
+      }
+      case 11: { // regex
+        // copy until closing 0
+        const unsigned char* uc = check_and_get_buffer_bson(buff, 1);
+        char *tmp_str = mcopystr(reinterpret_cast<const char*>(uc));
+        buff.increase_pos(strlen(tmp_str)+1);
+        char *regex = mprintf("\"%s\"", tmp_str);
+        Free(tmp_str);
+        uc = check_and_get_buffer_bson(buff, 1);
+        tmp_str = mcopystr(reinterpret_cast<const char*>(uc));
+        buff.increase_pos(strlen(tmp_str)+1);
+        char *options = mprintf("\"%s\"", tmp_str);
+        Free(tmp_str);
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        tok.put_next_token(JSON_TOKEN_NAME, "$regex");
+        tok.put_next_token(JSON_TOKEN_STRING, regex);
+        tok.put_next_token(JSON_TOKEN_NAME, "$options");
+        tok.put_next_token(JSON_TOKEN_STRING, options);
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        Free(options);
+        Free(regex);
+        break; }
+      case 12: { // dbref
+        INTEGER name_len = decode_int_bson(buff, 4);
+        const unsigned char* uc = check_and_get_buffer_bson(buff, (int)name_len);
+        char *tmp_name = mcopystrn(reinterpret_cast<const char*>(uc), (int)name_len);
+        buff.increase_pos((int)name_len);
+        char* tmp_str = mprintf("\"%s\"", tmp_name);
+        OCTETSTRING os(12, check_and_get_buffer_bson(buff, 12));
+        buff.increase_pos(12);
+        char* tmp_oct = NULL;
+        for (size_t i = 0; i < 12; i++) {
+          tmp_oct = mputprintf(tmp_oct, "%02X", os[i].get_octet());
+        }
+        char *str_hex = mprintf("\"%s\"", tmp_oct);
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        tok.put_next_token(JSON_TOKEN_NAME, "$ref");
+        tok.put_next_token(JSON_TOKEN_STRING, tmp_str);
+        tok.put_next_token(JSON_TOKEN_NAME, "$id");
+        tok.put_next_token(JSON_TOKEN_STRING, str_hex);
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        Free(tmp_oct);
+        Free(str_hex);
+        Free(tmp_str);
+        Free(tmp_name);
+        break; }
+      case 15: { // code_with_scope
+        INTEGER len = decode_int_bson(buff, 4);
+        check_and_get_buffer_bson(buff, (int)len-4); // len contains the length of itself
+        len = decode_int_bson(buff, 4);
+        const unsigned char* uc = check_and_get_buffer_bson(buff, (int)len);
+        char *tmp_str = mcopystrn(reinterpret_cast<const char*>(uc), (int)len);
+        char *tmp_str2 = mprintf("\"%s\"", tmp_str);
+        buff.increase_pos((int)len);
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        tok.put_next_token(JSON_TOKEN_NAME, "$code");
+        tok.put_next_token(JSON_TOKEN_STRING, tmp_str2);
+        tok.put_next_token(JSON_TOKEN_NAME, "$scope");
+        bson2json_coding(buff, tok, false, false);
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        Free(tmp_str2);
+        Free(tmp_str);
+        break; }
+      case 16: { // 32bit integer
+        INTEGER value = decode_int_bson(buff, 4);
+        char *tmp_str = mprintf("%d", (int)value);
+        tok.put_next_token(JSON_TOKEN_NUMBER, tmp_str);
+        Free(tmp_str);
+        break; }
+      case 17: { // timestamp
+        INTEGER increment = decode_int_bson(buff, 4);
+        INTEGER timestamp = decode_int_bson(buff, 4);
+        char *increment_str = mprintf("%i", (int)increment);
+        char *timestamp_str = mprintf("%i", (int)timestamp);
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        tok.put_next_token(JSON_TOKEN_NAME, "$timestamp");
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        tok.put_next_token(JSON_TOKEN_NAME, "t");
+        tok.put_next_token(JSON_TOKEN_STRING, timestamp_str);
+        tok.put_next_token(JSON_TOKEN_NAME, "i");
+        tok.put_next_token(JSON_TOKEN_STRING, increment_str);
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        Free(timestamp_str);
+        Free(increment_str);
+        break; }
+      case 18: { //64 bit integer
+        INTEGER value = decode_int_bson(buff, 8);
+        char *tmp_str = mprintf("%lld", value.get_long_long_val());
+        tok.put_next_token(JSON_TOKEN_NUMBER, tmp_str);
+        Free(tmp_str);
+        break; }
+      case 127: { // maxkey
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        tok.put_next_token(JSON_TOKEN_NAME, "$maxKey");
+        tok.put_next_token(JSON_TOKEN_NUMBER, "1");
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        break; }
+      case 255: { // minkey
+        tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+        tok.put_next_token(JSON_TOKEN_NAME, "$minKey");
+        tok.put_next_token(JSON_TOKEN_NUMBER, "1");
+        tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+        break; }
+      default:
+        TTCN_error("Unexpected type %i while decoding using bson2json().", *type);
+    }
+  }
+}
\ No newline at end of file
diff --git a/core/JSON.hh b/core/JSON.hh
index 767ae6ed636e201ae0bee630908f548674b26ce4..050df32201b2f08230b811674f156f2192cfa3b4 100644
--- a/core/JSON.hh
+++ b/core/JSON.hh
@@ -18,6 +18,8 @@
 
 class TTCN_Buffer;
 class JSON_Tokenizer;
+class CHARSTRING;
+class INTEGER;
 
 /** Descriptor for JSON encoding/decoding during runtime */
 struct TTCN_JSONdescriptor_t 
@@ -145,5 +147,9 @@ enum json_metainfo_t {
 void json2cbor_coding(TTCN_Buffer& buff, JSON_Tokenizer& tok, size_t& num_of_items);
 void cbor2json_coding(TTCN_Buffer& buff, JSON_Tokenizer& tok, bool in_object);
 
+// Functions for conversion between json and bson and vice versa
+void json2bson_coding(TTCN_Buffer& buff, JSON_Tokenizer& tok, bool in_object, bool in_array, INTEGER& length, CHARSTRING& f_name, bool& is_special);
+void bson2json_coding(TTCN_Buffer& buff, JSON_Tokenizer& tok, bool in_object, bool in_array);
+
 #endif	/* JSON_HH_ */
 
diff --git a/regression_test/json/.gitignore b/regression_test/json/.gitignore
index 47c5b42d6270c35a865a96183f953782ad234260..c04239387d25a26efaaea4ed1d30e94c0b34f127 100644
--- a/regression_test/json/.gitignore
+++ b/regression_test/json/.gitignore
@@ -16,5 +16,7 @@ Types*.cc
 Types*.hh
 Cbor*.cc
 Cbor*.hh
+Bson*.cc
+Bson*.hh
 logs
 compile
diff --git a/regression_test/json/Bson.ttcn b/regression_test/json/Bson.ttcn
new file mode 100644
index 0000000000000000000000000000000000000000..028d1c93ed95821fb25847d025f69adca4ee059e
--- /dev/null
+++ b/regression_test/json/Bson.ttcn
@@ -0,0 +1,580 @@
+module Bson {
+	
+	type component EmptyCT {
+
+	}
+
+	testcase tc_bson_encdec() runs on EmptyCT {
+		var octetstring os, expected_os;
+		var universal charstring json, decoded, decoded_json;
+
+		json := "{}"
+		expected_os := '0500000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":\"b\"}"
+		expected_os := '0E00000002610002000000620000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"aaaab\":\"bbbbbbc\"}"
+		expected_os := '180000000261616161620008000000626262626262630000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"ááá\":\"óóó\"}"
+		expected_os := '1800000002C3A1C3A1C3A10007000000C3B3C3B3C3B30000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":\"b\",\"c\":\"d\"}"
+		expected_os := '1700000002610002000000620002630002000000640000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":1}"
+		expected_os := '0C0000001061000100000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":15614615}"
+		expected_os := '0E00000010616263009742EE0000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":-15614615}"
+		expected_os := '0E000000106162630069BD11FF00'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+
+		json := "{\"abc\":4586797657}"
+		expected_os := '12000000126162630059FA64110100000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":-4586797657}"
+		expected_os := '120000001261626300A7059BEEFEFFFFFF00'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":1.120000}"
+		expected_os := '090000000161626300EC51B81E85EBF13F00'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":-11321.120465}"
+		expected_os := '090000000161626300A8A9656B8F1CC6C000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":true}"
+		expected_os := '0900000008616263000100'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":false}"
+		expected_os := '0900000008616263000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":null}"
+		expected_os := '090000000A6162630000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":[1]}"
+		expected_os := '1600000004616263000C000000103000010000000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":[1,2,\"abc\"]}"
+		expected_os := '2800000004616263001E000000103000010000001031000200000002320004000000616263000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":[1,2,[3,4],\"abc\"]}"
+		expected_os := '3E00000004616263003400000010300001000000103100020000000432001300000010300003000000103100040000000002320004000000616263000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":{\"def\":4}}"
+		expected_os := '1800000003616263000E0000001064656600040000000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":{\"a\":[2]}}"
+		expected_os := '1E0000000361626300140000000461000C00000010300002000000000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":[2,{\"a\":4}]}"
+		expected_os := '2500000004616263001B000000103000020000000331000C00000010610004000000000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"abc\":{\"def\":4,\"dd\":[1,2,3,{\"q\":3},3]},\"w\":[{\"a\":3}]}"
+		expected_os := '6300000003616263004200000010646566000400000004646400300000001030000100000010310002000000103200030000000333000C0000001071000300000000103400030000000000047700140000000330000C00000010610003000000000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+
+		// Special cases
+
+		json := "{\"a\":{\"$binary\":\"VEVTVCBUM1NU\",\"$type\":\"01\"}}"
+		expected_os := '16000000056100090000000154455354205433535400'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":{\"$binary\":\"VEVTVCBUM1NU\",\"$type\":\"01\"},\"b\":3}"
+		expected_os := '1D00000005610009000000015445535420543353541062000300000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":[{\"$binary\":\"VEVTVCBUM1NU\",\"$type\":\"01\"}],\"b\":3}"
+		expected_os := '25000000046100160000000530000900000001544553542054335354001062000300000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"b\":[{\"a\":[{\"$binary\":\"VEVTVCBUM1NU\",\"$type\":\"01\"}],\"b\":3}],\"c\":4532}"
+		expected_os := '3C0000000462002D0000000330002500000004610016000000053000090000000154455354205433535400106200030000000000106300B411000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":{\"$date\":{\"$numberLong\":345}}}"
+		expected_os := '10000000096100590100000000000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":[{\"$date\":{\"$numberLong\":345}}],\"b\":3}"
+		expected_os := '1F000000046100100000000930005901000000000000001062000300000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"b\":[{\"a\":[{\"$binary\":\"VEVTVCBUM1NU\",\"$type\":\"01\"},{\"$date\":{\"$numberLong\":34654776445}}],\"b\":3}],\"c\":4532}"
+		expected_os := '4700000004620038000000033000300000000461002100000005300009000000015445535420543353540930007DEC95110800000000106200030000000000106300B411000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":{\"$timestamp\":{\"t\":123,\"i\":456}}}"
+		expected_os := '10000000116100C80100007B00000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":[{\"$timestamp\":{\"t\":123,\"i\":456}}],\"b\":3}"
+		expected_os := '1F00000004610010000000113000C80100007B000000001062000300000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":{\"$regex\":\"myregex\",\"$options\":\"gim\"}}"
+		expected_os := '140000000b61006d7972656765780067696d0000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":[{\"$regex\":\"myregex\",\"$options\":\"gim\"}],\"b\":3}"
+		expected_os := '23000000046100140000000B30006D7972656765780067696D00001062000300000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":{\"$oid\":\"123456789ABCDEF123456789\"}}"
+		expected_os := '14000000076100123456789ABCDEF12345678900'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":[{\"$oid\":\"123456789ABCDEF123456789\"}],\"b\":3}"
+		expected_os := '2300000004610014000000073000123456789ABCDEF123456789001062000300000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":{\"$ref\":\"myname\",\"$id\":\"123456789ABCDEF123456789\"}}"
+		expected_os := '1F0000000C6100070000006D796E616D6500123456789ABCDEF12345678900'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":[{\"$ref\":\"myname\",\"$id\":\"123456789ABCDEF123456789\"}],\"b\":3}"
+		expected_os := '2E0000000461001F0000000C3000070000006D796E616D6500123456789ABCDEF123456789001062000300000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":{\"$undefined\":true}}"
+		expected_os := '0800000006610000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":[{\"$undefined\":true}],\"b\":3}"
+		expected_os := '1700000004610008000000063000001062000300000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":{\"$minKey\":1}}"
+		expected_os := '08000000FF610000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":[{\"$minKey\":1}],\"b\":3}"
+		expected_os := '1700000004610008000000FF3000001062000300000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":{\"$maxKey\":1}}"
+		expected_os := '080000007F610000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":[{\"$maxKey\":1}],\"b\":3}"
+		expected_os := '17000000046100080000007F3000001062000300000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		// Bad maxkey, encode as embedded document
+		json := "{\"a\":{\"$maxKey\":2}}"
+		expected_os := '1A0000000361001200000010246D61784B657900020000000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":{\"$numberLong\":\"123\"}}"
+		expected_os := '100000001261007B0000000000000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded_json := "{\"a\":123}"
+		decoded := bson2json(os);
+		if (not match(decoded, decoded_json)) {
+			setverdict(fail, match(decoded, decoded_json));
+		}
+
+		json := "{\"a\":{\"$numberLong\":\"12332232323232\"}}"
+		expected_os := '10000000126100A0B05352370B000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded_json := "{\"a\":12332232323232}"
+		decoded := bson2json(os);
+		if (not match(decoded, decoded_json)) {
+			setverdict(fail, match(decoded, decoded_json));
+		}
+
+		json := "{\"a\":[{\"$numberLong\":\"12332232323232\"}],\"b\":3}"
+		expected_os := '1F00000004610010000000123000A0B05352370B0000001062000300000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded_json := "{\"a\":[12332232323232],\"b\":3}"
+		decoded := bson2json(os);
+		if (not match(decoded, decoded_json)) {
+			setverdict(fail, match(decoded, decoded_json));
+		}
+
+		json := "{\"a\":{\"$code\":\"aaa\",\"$scope\":{\"a\":\"b\"}}}"
+		expected_os := '220000000F61001A00000004000000616161000E0000000261000200000062000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":[{\"$code\":\"aaa\",\"$scope\":{\"a\":\"b\"}}],\"b\":3}"
+		expected_os := '31000000046100220000000F30001A00000004000000616161000E00000002610002000000620000001062000300000000'O;
+		os := json2bson(json);log(os);
+		if (not match(os, expected_os)) {
+			setverdict(fail, match(os, expected_os));
+		}
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":\"aaa\"}"
+		// Javascript code. Cannot be produced from json
+		os := '100000000D6100040000006161610000'O;
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		json := "{\"a\":\"aaa\"}"
+		// Symbol. Cannot be produced from json
+		os := '100000000E6100040000006161610000'O;
+		decoded := bson2json(os);
+		if (not match(decoded, json)) {
+			setverdict(fail, match(decoded, json));
+		}
+
+		setverdict(pass);
+	}
+
+	control {
+		execute(tc_bson_encdec());
+	}
+}
\ No newline at end of file
diff --git a/regression_test/json/JSON.cfg b/regression_test/json/JSON.cfg
index 684b527d59c3b4bae4b384f9c18634d5be603f18..178cbdf935d528f32ffa50c0c4a49583eda34399 100644
--- a/regression_test/json/JSON.cfg
+++ b/regression_test/json/JSON.cfg
@@ -85,6 +85,7 @@ AttributeTestcases.control
 #AttributeTestcases.tc_attribute_prettyprint2
 #AttributeTestcases.tc_attribute_union
 Cbor.control
+Bson.control
 [GROUPS]
 # In this section you can specify groups of hosts. These groups can be used inside the
 # [COMPONENTS] section to restrict the creation of certain PTCs to a given set of hosts.
diff --git a/regression_test/json/Makefile b/regression_test/json/Makefile
index 6bce0e452385fe8073c1a2e57a2caa9588209114..3687365513db84a350944860e18a07f94772db3f 100644
--- a/regression_test/json/Makefile
+++ b/regression_test/json/Makefile
@@ -19,7 +19,7 @@ include $(TOPDIR)/Makefile.regression
 
 TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX)
 
-TTCN3_MODULES = Types.ttcn Functions.ttcn AttributeTestcases.ttcn Testcases.ttcn OtherTypes.ttcn SemanticCheck.ttcn Cbor.ttcn
+TTCN3_MODULES = Types.ttcn Functions.ttcn AttributeTestcases.ttcn Testcases.ttcn OtherTypes.ttcn SemanticCheck.ttcn Cbor.ttcn Bson.ttcn
 
 ifdef LEGACY_CODEC_HANDLING
 TTCN3_MODULES += SemanticCheck2.ttcn
diff --git a/usrguide/referenceguide.doc b/usrguide/referenceguide.doc
index 06da4541084bb168cf5bd0764aaba5df8871270e..2d0a4de28daee726c4c5ca3f1af1abb983fac98f 100644
Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ