diff --git a/compiler2/Type.cc b/compiler2/Type.cc
index cdb774e41af243d50eaaf74ce3bf1a68e6e55c5c..5cd91e85218837ea0e8524335bd06634e964c2c8 100644
--- a/compiler2/Type.cc
+++ b/compiler2/Type.cc
@@ -2780,8 +2780,22 @@ namespace Common {
           "field of a record or set.");
       }
 
-      if (jsonattrib->as_value && T_CHOICE_T != get_type_refd_last()->typetype) {
-        error("Invalid attribute, 'as value' is only allowed for unions");
+      if (jsonattrib->as_value) {
+        Type* last = get_type_refd_last();
+        switch (last->typetype) {
+        case T_CHOICE_T:
+        case T_ANYTYPE:
+          break; // OK
+        case T_SEQ_T:
+        case T_SET_T:
+          if (last->get_nof_comps() == 1) {
+            break; // OK
+          }
+          // else fall through
+        default:
+          error("Invalid attribute, 'as value' is only allowed for unions, "
+            "the anytype, or records or sets with one field");
+        }
       }
 
       if (NULL != jsonattrib->alias) {
@@ -2792,9 +2806,34 @@ namespace Common {
             "record, set or union.");
         }
         if (NULL != parent && NULL != parent->jsonattrib && 
-            T_CHOICE_T == parent->typetype && parent->jsonattrib->as_value) {
-          warning("Attribute 'name as ...' will be ignored, because parent union "
-            "is encoded without field names.");
+            parent->jsonattrib->as_value) {
+          const char* parent_type_name = NULL;
+          switch (parent->typetype) {
+          case T_SEQ_T:
+            if (parent->get_nof_comps() == 1) {
+              parent_type_name = "record";
+            }
+            break;
+          case T_SET_T:
+            if (parent->get_nof_comps() == 1) {
+              parent_type_name = "set";
+            }
+            break;
+          case T_CHOICE_T:
+            parent_type_name = "union";
+            break;
+          case T_ANYTYPE:
+            parent_type_name = "anytype";
+            break;
+          default:
+            break;
+          }
+          if (parent_type_name != NULL) {
+            // parent_type_name remains null if the 'as value' attribute is set
+            // for an invalid type
+            warning("Attribute 'name as ...' will be ignored, because parent %s "
+              "is encoded without field names.", parent_type_name);
+          }
         }
       }
 
@@ -2846,24 +2885,29 @@ namespace Common {
         delete[] checked_keywords;
       }
       if (jsonattrib->metainfo_unbound) {
+        Type* last = get_type_refd_last();
         Type* parent = get_parent_type();
-        if (T_SEQ_T == get_type_refd_last()->typetype ||
-            T_SET_T == get_type_refd_last()->typetype) {
+        if (T_SEQ_T == last->typetype || T_SET_T == last->typetype) {
           // if it's set for the record/set, pass it onto its fields
-          size_t nof_comps = get_nof_comps();
-          for (size_t i = 0; i < nof_comps; i++) {
-            Type* comp_type = get_comp_byIndex(i)->get_type();
-            if (NULL == comp_type->jsonattrib) {
-              comp_type->jsonattrib = new JsonAST;
+          size_t nof_comps = last->get_nof_comps();
+          if (jsonattrib->as_value && nof_comps == 1) {
+            warning("Attribute 'metainfo for unbound' will be ignored, because "
+              "the %s is encoded without field names.",
+              T_SEQ_T == last->typetype ? "record" : "set");
+          }
+          else {
+            for (size_t i = 0; i < nof_comps; i++) {
+              Type* comp_type = last->get_comp_byIndex(i)->get_type();
+              if (NULL == comp_type->jsonattrib) {
+                comp_type->jsonattrib = new JsonAST;
+              }
+              comp_type->jsonattrib->metainfo_unbound = true;
             }
-            comp_type->jsonattrib->metainfo_unbound = true;
           }
         }
-        else if (T_SEQOF != get_type_refd_last()->typetype &&
-                 T_SETOF != get_type_refd_last()->typetype &&
-                 T_ARRAY != get_type_refd_last()->typetype &&
-                 (NULL == parent || (T_SEQ_T != parent->typetype &&
-                  T_SET_T != parent->typetype))) {
+        else if (T_SEQOF != last->typetype && T_SETOF != last->typetype &&
+                 T_ARRAY != last->typetype && (NULL == parent ||
+                 (T_SEQ_T != parent->typetype && T_SET_T != parent->typetype))) {
           // only allowed if it's an array type or a field of a record/set
           error("Invalid attribute 'metainfo for unbound', requires record, set, "
             "record of, set of, array or field of a record or set");
diff --git a/compiler2/Type_codegen.cc b/compiler2/Type_codegen.cc
index 0e7fd7ce97b5fa4ccffcd0b4bcd75d7673e63d0b..91bba9d300b02de9fe456497b40327a7d37a8c00 100644
--- a/compiler2/Type_codegen.cc
+++ b/compiler2/Type_codegen.cc
@@ -1207,7 +1207,7 @@ void Type::generate_code_Choice(output_struct *target)
         sdef.elements[i].xerUseUnion = cftype->xerattrib->useUnion_;
       }
     }
-    if (sdef.jsonAsValue) {
+    if (sdef.hasJson && enable_json()) {
       // Determine the JSON value type of each field to make decoding faster
       typetype_t tt = cftype->get_type_refd_last()->typetype;
       switch(tt) {
@@ -1253,11 +1253,16 @@ void Type::generate_code_Choice(output_struct *target)
       case T_SEQ_A:
       case T_SET_T:
       case T_SET_A:
+        if (cftype->get_type_refd_last()->get_nof_comps() > 1) {
+          sdef.elements[i].jsonValueType = JSON_OBJECT;
+          break;
+        }
+        // else fall through
       case T_CHOICE_T:
       case T_CHOICE_A:
       case T_ANYTYPE:
       case T_OPENTYPE:
-        sdef.elements[i].jsonValueType = JSON_OBJECT;
+        sdef.elements[i].jsonValueType = JSON_ANY_VALUE;
         break;
       case T_SEQOF:
       case T_SETOF:
@@ -1270,10 +1275,6 @@ void Type::generate_code_Choice(output_struct *target)
     }
     if (cftype->jsonattrib) {
       sdef.elements[i].jsonAlias = cftype->jsonattrib->alias;
-      if (sdef.jsonAsValue && cftype->jsonattrib->as_value) {
-        // Override the JSON_OBJECT value given in the switch
-        sdef.elements[i].jsonValueType = JSON_ANY_VALUE;
-      }
     }
   }
   if(rawattrib) {
diff --git a/compiler2/datatypes.h b/compiler2/datatypes.h
index 95f376e77b59883e197c7314b0ee0e7288cc6c41..19da16ceef0360b60e7eebb4ded5a89cb1dcffdd 100644
--- a/compiler2/datatypes.h
+++ b/compiler2/datatypes.h
@@ -112,7 +112,7 @@ typedef struct {
   boolean xerUseUnion; /* for choice */
   boolean xerHasNamespaces; /* from the module */
   boolean xerEmbedValuesPossible; /* for sequence */
-  boolean jsonAsValue; /* for choice */
+  boolean jsonAsValue; /* for both */
   /** The index of the last field which can generate empty XML, or -1 */
   int exerMaybeEmptyIndex; /* for union */
   const char * control_ns_prefix;
diff --git a/compiler2/record.c b/compiler2/record.c
index 4b1c131d186846b9d47151dc4034994a7cab6ad8..27bd00cfa5138f2823d75126511dfab3b2111824 100644
--- a/compiler2/record.c
+++ b/compiler2/record.c
@@ -4373,237 +4373,262 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
   if (json_needed) {
     // JSON encode, RT1
     src = mputprintf(src,
-      "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
+      "int %s::JSON_encode(const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok) const\n"
       "{\n"
       "  if (!is_bound()) {\n"
       "    TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
       "      \"Encoding an unbound value of type %s.\");\n"
       "    return -1;\n"
-      "  }\n\n"
-      "  int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n"
-      , name, dispname);
-    for (i = 0; i < sdef->nElements; ++i) {
-      if (sdef->elements[i].isOptional && !sdef->elements[i].jsonOmitAsNull &&
-          !sdef->elements[i].jsonMetainfoUnbound) {
-        src = mputprintf(src,
-          "  if (field_%s.is_present())\n"
-          , sdef->elements[i].name);
+      "  }\n\n", name, !sdef->jsonAsValue ? " p_td" : "", dispname);
+    if (sdef->nElements == 1) {
+      if (!sdef->jsonAsValue) {
+        src = mputstr(src, "  if (NULL != p_td.json && p_td.json->as_value) {\n");
       }
-      src = mputprintf(src,
-        "  {\n"
-        "    enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n    "
-        , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
-      if (sdef->elements[i].jsonMetainfoUnbound) {
+      src = mputprintf(src, "  %sreturn field_%s.JSON_encode(%s_descr_, p_tok);\n",
+        sdef->jsonAsValue ? "" : "  ", sdef->elements[0].name, sdef->elements[0].typedescrname);
+      if (!sdef->jsonAsValue) {
+        src = mputstr(src, "  }\n");
+      }
+    }
+    if (!sdef->jsonAsValue) {
+      src = mputstr(src, "  int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n");
+      for (i = 0; i < sdef->nElements; ++i) {
+        if (sdef->elements[i].isOptional && !sdef->elements[i].jsonOmitAsNull &&
+            !sdef->elements[i].jsonMetainfoUnbound) {
+          src = mputprintf(src,
+            "  if (field_%s.is_present())\n"
+            , sdef->elements[i].name);
+        }
         src = mputprintf(src,
-          "if (!field_%s.is_bound()) {\n"
-          "      enc_len += p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL);\n"
-          "      enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"metainfo %s\");\n"
-          "      enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, \"\\\"unbound\\\"\");\n"
-          "    }\n"
-          "    else "
-          , sdef->elements[i].name
+          "  {\n"
+          "    enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n    "
           , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
+        if (sdef->elements[i].jsonMetainfoUnbound) {
+          src = mputprintf(src,
+            "if (!field_%s.is_bound()) {\n"
+            "      enc_len += p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL);\n"
+            "      enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"metainfo %s\");\n"
+            "      enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, \"\\\"unbound\\\"\");\n"
+            "    }\n"
+            "    else "
+            , sdef->elements[i].name
+            , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
+        }
+        src = mputprintf(src,
+          "enc_len += field_%s.JSON_encode(%s_descr_, p_tok);\n"
+          "  }\n\n"
+          , sdef->elements[i].name, sdef->elements[i].typedescrname);
       }
-      src = mputprintf(src,
-        "enc_len += field_%s.JSON_encode(%s_descr_, p_tok);\n"
-        "  }\n\n"
-        , sdef->elements[i].name, sdef->elements[i].typedescrname);
+      src = mputstr(src, 
+        "  enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n"
+        "  return enc_len;\n");
     }
-    src = mputstr(src, 
-      "  enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n"
-      "  return enc_len;\n"
-      "}\n\n");
+    src = mputstr(src, "}\n\n");
     
     // JSON decode, RT1
     src = mputprintf(src,
-      "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
-      "{\n"
-      "  json_token_t j_token = JSON_TOKEN_NONE;\n"
-      "  size_t dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n"
-      "  if (JSON_TOKEN_ERROR == j_token) {\n"
-      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
-      "    return JSON_ERROR_FATAL;\n"
-      "  }\n"
-      "  else if (JSON_TOKEN_OBJECT_START != j_token) {\n"
-      "    return JSON_ERROR_INVALID_TOKEN;\n"
-      "  }\n"
-      , name);
-    boolean has_metainfo_enabled = FALSE;
-    for (i = 0; i < sdef->nElements; ++i) {
-      src = mputprintf(src, "  boolean %s_found = FALSE;\n", sdef->elements[i].name);
-      if (sdef->elements[i].jsonMetainfoUnbound) {
-        // initialize meta info states
-        src = mputprintf(src, 
-          "  int metainfo_%s = JSON_METAINFO_NONE;\n"
-          , sdef->elements[i].name);
-        has_metainfo_enabled = TRUE;
+      "int %s::JSON_decode(const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok, boolean p_silent)\n"
+      "{\n", name, !sdef->jsonAsValue ? " p_td" : "");
+    
+    if (sdef->nElements == 1) {
+      if (!sdef->jsonAsValue) {
+        src = mputstr(src, "  if (NULL != p_td.json && p_td.json->as_value) {\n");
+      }
+      src = mputprintf(src, "  %sreturn field_%s.JSON_decode(%s_descr_, p_tok, p_silent);\n",
+        sdef->jsonAsValue ? "" : "  ", sdef->elements[0].name, sdef->elements[0].typedescrname);
+      if (!sdef->jsonAsValue) {
+        src = mputstr(src, "  }\n");
       }
     }
-    src = mputstr(src,
-      // Read name - value token pairs until we reach some other token
-      "\n  while (TRUE) {\n"
-      "    char* fld_name = 0;\n"
-      "    size_t name_len = 0;\n"
-      "    size_t buf_pos = p_tok.get_buf_pos();\n"
-      "    dec_len += p_tok.get_next_token(&j_token, &fld_name, &name_len);\n"
-      "    if (JSON_TOKEN_ERROR == j_token) {\n"
-      "      JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_NAME_TOKEN_ERROR);\n"
-      "      return JSON_ERROR_FATAL;\n"
-      "    }\n"
-           // undo the last action on the buffer
-      "    else if (JSON_TOKEN_NAME != j_token) {\n"
-      "      p_tok.set_buf_pos(buf_pos);\n"
-      "      break;\n"
-      "    }\n"
-      "    else {\n      ");
-    if (has_metainfo_enabled) {
-      // check for meta info
+    if (!sdef->jsonAsValue) {
       src = mputstr(src,
-        "boolean is_metainfo = FALSE;\n"
-        "      if (name_len > 9 && 0 == strncmp(fld_name, \"metainfo \", 9)) {\n"
-        "        fld_name += 9;\n"
-        "        name_len -= 9;\n"
-        "        is_metainfo = TRUE;\n"
-        "      }\n      ");
-    }
-    for (i = 0; i < sdef->nElements; ++i) {
-      src = mputprintf(src,
-        // check field name
-        "if (%d == name_len && 0 == strncmp(fld_name, \"%s\", name_len)) {\n"
-        "        %s_found = TRUE;\n"
-        , (int)strlen(sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname)
-        , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname
-        , sdef->elements[i].name);
-      if (has_metainfo_enabled) {
-        src = mputstr(src, "        if (is_metainfo) {\n");
-        if (sdef->elements[i].jsonMetainfoUnbound) {
-          src = mputprintf(src,
-            // check meta info
-            "          char* info_value = 0;\n"
-            "          size_t info_len = 0;\n"
-            "          dec_len += p_tok.get_next_token(&j_token, &info_value, &info_len);\n"
-            "          if (JSON_TOKEN_STRING == j_token && 9 == info_len &&\n"
-            "              0 == strncmp(info_value, \"\\\"unbound\\\"\", 9)) {\n"
-            "            metainfo_%s = JSON_METAINFO_UNBOUND;\n"
-            "          }\n"
-            "          else {\n"
-            "            JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_VALUE_ERROR, \"%s\");\n"
-            "            return JSON_ERROR_FATAL;\n"
-            "          }\n"
-            , sdef->elements[i].name, sdef->elements[i].dispname);
-        }
-        else {
-          src = mputprintf(src,
-            "          JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_NOT_APPLICABLE, \"%s\");\n"
-            "          return JSON_ERROR_FATAL;\n"
-            , sdef->elements[i].dispname);
-        }
-        src = mputstr(src,
-          "        }\n"
-          "        else {\n");
+        "  json_token_t j_token = JSON_TOKEN_NONE;\n"
+        "  size_t dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n"
+        "  if (JSON_TOKEN_ERROR == j_token) {\n"
+        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
+        "    return JSON_ERROR_FATAL;\n"
+        "  }\n"
+        "  else if (JSON_TOKEN_OBJECT_START != j_token) {\n"
+        "    return JSON_ERROR_INVALID_TOKEN;\n"
+        "  }\n");
+
+      boolean has_metainfo_enabled = FALSE;
+      for (i = 0; i < sdef->nElements; ++i) {
+        src = mputprintf(src, "  boolean %s_found = FALSE;\n", sdef->elements[i].name);
         if (sdef->elements[i].jsonMetainfoUnbound) {
-          src = mputstr(src, "         buf_pos = p_tok.get_buf_pos();\n");
+          // initialize meta info states
+          src = mputprintf(src, 
+            "  int metainfo_%s = JSON_METAINFO_NONE;\n"
+            , sdef->elements[i].name);
+          has_metainfo_enabled = TRUE;
         }
       }
-      src = mputprintf(src,
-        "         int ret_val = field_%s.JSON_decode(%s_descr_, p_tok, p_silent);\n"
-        "         if (0 > ret_val) {\n"
-        "           if (JSON_ERROR_INVALID_TOKEN == ret_val) {\n"
-        , sdef->elements[i].name, sdef->elements[i].typedescrname);
-      if (sdef->elements[i].jsonMetainfoUnbound) {
-        src = mputprintf(src,
-          // undo the last action on the buffer, check if the invalid token was a null token 
-          "             p_tok.set_buf_pos(buf_pos);\n"
-          "             p_tok.get_next_token(&j_token, NULL, NULL);\n"
-          "             if (JSON_TOKEN_LITERAL_NULL == j_token) {\n"
-          "               if (JSON_METAINFO_NONE == metainfo_%s) {\n"
-          // delay reporting an error for now, there might be meta info later
-          "                 metainfo_%s = JSON_METAINFO_NEEDED;\n"
-          "                 continue;\n"
-          "               }\n"
-          "               else if (JSON_METAINFO_UNBOUND == metainfo_%s) {\n"
-          // meta info already found
-          "                 continue;\n"
-          "               }\n"
-          "             }\n"
-          , sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name);
-      }
-      src = mputprintf(src,
-        "             JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, %lu, \"%s\");\n"
-        "           }\n"
-        "           return JSON_ERROR_FATAL;\n"
-        "         }\n"
-        "         dec_len += (size_t)ret_val;\n"
-        , (unsigned long) strlen(sdef->elements[i].dispname), sdef->elements[i].dispname);
+      src = mputstr(src,
+        // Read name - value token pairs until we reach some other token
+        "\n  while (TRUE) {\n"
+        "    char* fld_name = 0;\n"
+        "    size_t name_len = 0;\n"
+        "    size_t buf_pos = p_tok.get_buf_pos();\n"
+        "    dec_len += p_tok.get_next_token(&j_token, &fld_name, &name_len);\n"
+        "    if (JSON_TOKEN_ERROR == j_token) {\n"
+        "      JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_NAME_TOKEN_ERROR);\n"
+        "      return JSON_ERROR_FATAL;\n"
+        "    }\n"
+             // undo the last action on the buffer
+        "    else if (JSON_TOKEN_NAME != j_token) {\n"
+        "      p_tok.set_buf_pos(buf_pos);\n"
+        "      break;\n"
+        "    }\n"
+        "    else {\n      ");
       if (has_metainfo_enabled) {
-        src = mputstr(src, "        }\n");
+        // check for meta info
+        src = mputstr(src,
+          "boolean is_metainfo = FALSE;\n"
+          "      if (name_len > 9 && 0 == strncmp(fld_name, \"metainfo \", 9)) {\n"
+          "        fld_name += 9;\n"
+          "        name_len -= 9;\n"
+          "        is_metainfo = TRUE;\n"
+          "      }\n      ");
       }
-      src = mputstr(src,
-        "      }\n"
-        "      else ");
-    }
-    src = mputprintf(src,
-      "{\n"
-               // invalid field name
-      "        JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, %sJSON_DEC_INVALID_NAME_ERROR, (int)name_len, fld_name);\n"
-               // if this is set to a warning, skip the value of the field
-      "        dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
-      "        if (JSON_TOKEN_NUMBER != j_token && JSON_TOKEN_STRING != j_token &&\n"
-      "            JSON_TOKEN_LITERAL_TRUE != j_token && JSON_TOKEN_LITERAL_FALSE != j_token &&\n"
-      "            JSON_TOKEN_LITERAL_NULL != j_token) {\n"
-      "          JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, (int)name_len, fld_name);\n"
-      "          return JSON_ERROR_FATAL;\n"
-      "        }\n"
-      "      }\n"
-      "    }\n"
-      "  }\n\n"
-      "  dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
-      "  if (JSON_TOKEN_OBJECT_END != j_token) {\n"
-      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_OBJECT_END_TOKEN_ERROR, \"\");\n"
-      "    return JSON_ERROR_FATAL;\n"
-      "  }\n\n  "
-      , has_metainfo_enabled ? "is_metainfo ?\n          JSON_DEC_METAINFO_NAME_ERROR : " : "");
-    // Check if every field has been set and handle meta info
-    for (i = 0; i < sdef->nElements; ++i) {
-      if (sdef->elements[i].jsonMetainfoUnbound) {
+      for (i = 0; i < sdef->nElements; ++i) {
         src = mputprintf(src,
-          "if (JSON_METAINFO_UNBOUND == metainfo_%s) {\n"
-          "    field_%s.clean_up();\n"
-          "  }\n"
-          "  else if (JSON_METAINFO_NEEDED == metainfo_%s) {\n"
-          // no meta info was found for this field, report the delayed error
-          "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, %lu, \"%s\");\n"
-          "  }\n"
-          "  else "
-          , sdef->elements[i].name, sdef->elements[i].name
-          , sdef->elements[i].name
-          , (unsigned long) strlen(sdef->elements[i].dispname)
-          , sdef->elements[i].dispname);
-      }
-      src = mputprintf(src,
-        "  if (!%s_found) {\n"
-        , sdef->elements[i].name);
-      if (sdef->elements[i].jsonDefaultValue) {
+          // check field name
+          "if (%d == name_len && 0 == strncmp(fld_name, \"%s\", name_len)) {\n"
+          "        %s_found = TRUE;\n"
+          , (int)strlen(sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname)
+          , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname
+          , sdef->elements[i].name);
+        if (has_metainfo_enabled) {
+          src = mputstr(src, "        if (is_metainfo) {\n");
+          if (sdef->elements[i].jsonMetainfoUnbound) {
+            src = mputprintf(src,
+              // check meta info
+              "          char* info_value = 0;\n"
+              "          size_t info_len = 0;\n"
+              "          dec_len += p_tok.get_next_token(&j_token, &info_value, &info_len);\n"
+              "          if (JSON_TOKEN_STRING == j_token && 9 == info_len &&\n"
+              "              0 == strncmp(info_value, \"\\\"unbound\\\"\", 9)) {\n"
+              "            metainfo_%s = JSON_METAINFO_UNBOUND;\n"
+              "          }\n"
+              "          else {\n"
+              "            JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_VALUE_ERROR, \"%s\");\n"
+              "            return JSON_ERROR_FATAL;\n"
+              "          }\n"
+              , sdef->elements[i].name, sdef->elements[i].dispname);
+          }
+          else {
+            src = mputprintf(src,
+              "          JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_NOT_APPLICABLE, \"%s\");\n"
+              "          return JSON_ERROR_FATAL;\n"
+              , sdef->elements[i].dispname);
+          }
+          src = mputstr(src,
+            "        }\n"
+            "        else {\n");
+          if (sdef->elements[i].jsonMetainfoUnbound) {
+            src = mputstr(src, "         buf_pos = p_tok.get_buf_pos();\n");
+          }
+        }
         src = mputprintf(src,
-          "    field_%s.JSON_decode(%s_descr_, DUMMY_BUFFER, p_silent);\n"
+          "         int ret_val = field_%s.JSON_decode(%s_descr_, p_tok, p_silent);\n"
+          "         if (0 > ret_val) {\n"
+          "           if (JSON_ERROR_INVALID_TOKEN == ret_val) {\n"
           , sdef->elements[i].name, sdef->elements[i].typedescrname);
+        if (sdef->elements[i].jsonMetainfoUnbound) {
+          src = mputprintf(src,
+            // undo the last action on the buffer, check if the invalid token was a null token 
+            "             p_tok.set_buf_pos(buf_pos);\n"
+            "             p_tok.get_next_token(&j_token, NULL, NULL);\n"
+            "             if (JSON_TOKEN_LITERAL_NULL == j_token) {\n"
+            "               if (JSON_METAINFO_NONE == metainfo_%s) {\n"
+            // delay reporting an error for now, there might be meta info later
+            "                 metainfo_%s = JSON_METAINFO_NEEDED;\n"
+            "                 continue;\n"
+            "               }\n"
+            "               else if (JSON_METAINFO_UNBOUND == metainfo_%s) {\n"
+            // meta info already found
+            "                 continue;\n"
+            "               }\n"
+            "             }\n"
+            , sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name);
+        }
+        src = mputprintf(src,
+          "             JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, %lu, \"%s\");\n"
+          "           }\n"
+          "           return JSON_ERROR_FATAL;\n"
+          "         }\n"
+          "         dec_len += (size_t)ret_val;\n"
+          , (unsigned long) strlen(sdef->elements[i].dispname), sdef->elements[i].dispname);
+        if (has_metainfo_enabled) {
+          src = mputstr(src, "        }\n");
+        }
+        src = mputstr(src,
+          "      }\n"
+          "      else ");
       }
-      else if (sdef->elements[i].isOptional) {
+      src = mputprintf(src,
+        "{\n"
+                 // invalid field name
+        "        JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, %sJSON_DEC_INVALID_NAME_ERROR, (int)name_len, fld_name);\n"
+                 // if this is set to a warning, skip the value of the field
+        "        dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
+        "        if (JSON_TOKEN_NUMBER != j_token && JSON_TOKEN_STRING != j_token &&\n"
+        "            JSON_TOKEN_LITERAL_TRUE != j_token && JSON_TOKEN_LITERAL_FALSE != j_token &&\n"
+        "            JSON_TOKEN_LITERAL_NULL != j_token) {\n"
+        "          JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, (int)name_len, fld_name);\n"
+        "          return JSON_ERROR_FATAL;\n"
+        "        }\n"
+        "      }\n"
+        "    }\n"
+        "  }\n\n"
+        "  dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
+        "  if (JSON_TOKEN_OBJECT_END != j_token) {\n"
+        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_OBJECT_END_TOKEN_ERROR, \"\");\n"
+        "    return JSON_ERROR_FATAL;\n"
+        "  }\n\n  "
+        , has_metainfo_enabled ? "is_metainfo ?\n          JSON_DEC_METAINFO_NAME_ERROR : " : "");
+      // Check if every field has been set and handle meta info
+      for (i = 0; i < sdef->nElements; ++i) {
+        if (sdef->elements[i].jsonMetainfoUnbound) {
+          src = mputprintf(src,
+            "if (JSON_METAINFO_UNBOUND == metainfo_%s) {\n"
+            "    field_%s.clean_up();\n"
+            "  }\n"
+            "  else if (JSON_METAINFO_NEEDED == metainfo_%s) {\n"
+            // no meta info was found for this field, report the delayed error
+            "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, %lu, \"%s\");\n"
+            "  }\n"
+            "  else "
+            , sdef->elements[i].name, sdef->elements[i].name
+            , sdef->elements[i].name
+            , (unsigned long) strlen(sdef->elements[i].dispname)
+            , sdef->elements[i].dispname);
+        }
         src = mputprintf(src,
-          "    field_%s = OMIT_VALUE;\n"
+          "  if (!%s_found) {\n"
           , sdef->elements[i].name);
-      } else {
-        src = mputprintf(src,
-          "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_MISSING_FIELD_ERROR, \"%s\");\n"
-          "    return JSON_ERROR_FATAL;\n"
-          , sdef->elements[i].dispname);
+        if (sdef->elements[i].jsonDefaultValue) {
+          src = mputprintf(src,
+            "    field_%s.JSON_decode(%s_descr_, DUMMY_BUFFER, p_silent);\n"
+            , sdef->elements[i].name, sdef->elements[i].typedescrname);
+        }
+        else if (sdef->elements[i].isOptional) {
+          src = mputprintf(src,
+            "    field_%s = OMIT_VALUE;\n"
+            , sdef->elements[i].name);
+        } else {
+          src = mputprintf(src,
+            "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_MISSING_FIELD_ERROR, \"%s\");\n"
+            "    return JSON_ERROR_FATAL;\n"
+            , sdef->elements[i].dispname);
+        }
+        src = mputstr(src,
+          "  }\n");
       }
       src = mputstr(src,
-        "  }\n");
+        "\n  return (int)dec_len;\n");
     }
-    src = mputstr(src,
-      "\n  return (int)dec_len;\n"
-      "}\n\n");
+    src = mputstr(src, "}\n\n");
   }
   
   /* end of class definition */
diff --git a/compiler2/union.c b/compiler2/union.c
index 3223e47d0600ec2dfe79371486c63a0062cb88ac..21fe71e1b02ce62da60004171059b3953d807359 100644
--- a/compiler2/union.c
+++ b/compiler2/union.c
@@ -2009,21 +2009,29 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
     // JSON encode
     src = mputprintf(src,
       "int %s::JSON_encode(const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok) const\n"
-      "{\n", name, use_runtime_2 ? " p_td" : "");
+      "{\n", name, (use_runtime_2 || !sdef->jsonAsValue) ? " p_td" : "");
     if (use_runtime_2) {
       src = mputstr(src, "  if (err_descr) return JSON_encode_negtest(err_descr, p_td, p_tok);\n");
     }
     if (!sdef->jsonAsValue) {
-      src = mputstr(src, "  int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n");
+      // 'as value' is not set for the base type, but it might still be set in
+      // the type descriptor
+      src = mputstr(src, 
+        "  boolean as_value = NULL != p_td.json && p_td.json->as_value;\n"
+        "  int enc_len = as_value ? 0 : "
+        "p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n");
     } else {
-      src = mputstr(src, "  int enc_len = 0;\n\n");
+      src = mputstr(src, "  int enc_len = 0;\n");
     }
     src = mputstr(src, "  switch(union_selection) {\n");
       
     for (i = 0; i < sdef->nElements; ++i) {
       src = mputprintf(src, "  case %s_%s:\n", selection_prefix, sdef->elements[i].name);
       if (!sdef->jsonAsValue) {
-        src = mputprintf(src, "    enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
+        src = mputprintf(src,
+          "    if (!as_value) {\n"
+          "      enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
+          "    }\n"
           , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
       }
       src = mputprintf(src, 
@@ -2039,7 +2047,10 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
       "  }\n\n"
       , dispname);
     if (!sdef->jsonAsValue) {
-      src = mputstr(src, "  enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n");
+      src = mputstr(src,
+        "  if (!as_value) {\n"
+        "    enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n"
+        "  }\n");
     }
     src = mputstr(src,
       "  return enc_len;\n"
@@ -2052,10 +2063,15 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
         "const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;\n");
       src = mputprintf(src,
         "int %s::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr, "
-        "const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
-        "{\n", name);
+        "const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok) const\n"
+        "{\n", name, !sdef->jsonAsValue ? " p_td" : "");
       if (!sdef->jsonAsValue) {
-        src = mputstr(src, "  int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n");
+        // 'as value' is not set for the base type, but it might still be set in
+        // the type descriptor
+        src = mputstr(src, 
+          "  boolean as_value = NULL != p_td.json && p_td.json->as_value;\n"
+          "  int enc_len = as_value ? 0 : "
+          "p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n");
       } else {
         src = mputstr(src, "  int enc_len = 0;\n\n");
       }
@@ -2079,7 +2095,10 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
           "          }\n"
           , selection_prefix, sdef->elements[i].name, (int)i, (int)i);
         if (!sdef->jsonAsValue) {
-          src = mputprintf(src, "          enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
+          src = mputprintf(src,
+            "          if (!as_value) {\n"
+            "            enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
+            "          }\n"
             , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
         }
         src = mputstr(src,
@@ -2088,7 +2107,10 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
           "      }\n"
           "    } else {\n");
         if (!sdef->jsonAsValue) {
-          src = mputprintf(src, "      enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
+          src = mputprintf(src,
+            "      if (!as_value) {\n"
+            "        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
+            "      }\n"
             , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
         }
         src = mputprintf(src,
@@ -2110,7 +2132,10 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
         "  }\n\n"
         , dispname);
       if (!sdef->jsonAsValue) {
-        src = mputstr(src, "  enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n");
+        src = mputstr(src,
+          "  if (!as_value) {\n"
+          "    enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n"
+          "}\n");
       }
       src = mputstr(src,
         "  return enc_len;\n"
@@ -2119,133 +2144,137 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
     
     // JSON decode
     src = mputprintf(src,
-      "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
+      "int %s::JSON_decode(const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok, boolean p_silent)\n"
       "{\n"
       "  json_token_t j_token = JSON_TOKEN_NONE;\n"
-      , name);
-    if (sdef->jsonAsValue) {
+      , name, !sdef->jsonAsValue ? " p_td" : "");
+    if (!sdef->jsonAsValue) {
       src = mputstr(src,
-        "  size_t buf_pos = p_tok.get_buf_pos();\n"
-        "  p_tok.get_next_token(&j_token, NULL, NULL);\n"
-        "  int ret_val = 0;\n"
-        "  switch(j_token) {\n"
-        "  case JSON_TOKEN_NUMBER: {\n");
-      for (i = 0; i < sdef->nElements; ++i) {
-        if (JSON_NUMBER & sdef->elements[i].jsonValueType) {
-          src = mputprintf(src,
-            "    p_tok.set_buf_pos(buf_pos);\n"
-            "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
-            "    if (0 <= ret_val) {\n"
-            "      return ret_val;\n"
-            "    }\n"
-            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
-        }
+        " if (NULL != p_td.json && p_td.json->as_value) {\n");
+    }
+    src = mputstr(src,
+      "  size_t buf_pos = p_tok.get_buf_pos();\n"
+      "  p_tok.get_next_token(&j_token, NULL, NULL);\n"
+      "  int ret_val = 0;\n"
+      "  switch(j_token) {\n"
+      "  case JSON_TOKEN_NUMBER: {\n");
+    for (i = 0; i < sdef->nElements; ++i) {
+      if (JSON_NUMBER & sdef->elements[i].jsonValueType) {
+        src = mputprintf(src,
+          "    p_tok.set_buf_pos(buf_pos);\n"
+          "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
+          "    if (0 <= ret_val) {\n"
+          "      return ret_val;\n"
+          "    }\n"
+          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
       }
-      src = mputstr(src,
-        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"number\");\n"
-        "    clean_up();\n"
-        "    return JSON_ERROR_FATAL;\n"
-        "  }\n"
-        "  case JSON_TOKEN_STRING: {\n");
-      for (i = 0; i < sdef->nElements; ++i) {
-        if (JSON_STRING & sdef->elements[i].jsonValueType) {
-          src = mputprintf(src,
-            "    p_tok.set_buf_pos(buf_pos);\n"
-            "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
-            "    if (0 <= ret_val) {\n"
-            "      return ret_val;\n"
-            "    }\n"
-            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
-        }
+    }
+    src = mputstr(src,
+      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"number\");\n"
+      "    clean_up();\n"
+      "    return JSON_ERROR_FATAL;\n"
+      "  }\n"
+      "  case JSON_TOKEN_STRING: {\n");
+    for (i = 0; i < sdef->nElements; ++i) {
+      if (JSON_STRING & sdef->elements[i].jsonValueType) {
+        src = mputprintf(src,
+          "    p_tok.set_buf_pos(buf_pos);\n"
+          "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
+          "    if (0 <= ret_val) {\n"
+          "      return ret_val;\n"
+          "    }\n"
+          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
       }
-      src = mputstr(src,
-        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"string\");\n"
-        "    clean_up();\n"
-        "    return JSON_ERROR_FATAL;\n"
-        "  }\n"
-        "  case JSON_TOKEN_LITERAL_TRUE:\n"
-        "  case JSON_TOKEN_LITERAL_FALSE: {\n");
-      for (i = 0; i < sdef->nElements; ++i) {
-        if (JSON_BOOLEAN & sdef->elements[i].jsonValueType) {
-          src = mputprintf(src,
-            "    p_tok.set_buf_pos(buf_pos);\n"
-            "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
-            "    if (0 <= ret_val) {\n"
-            "      return ret_val;\n"
-            "    }\n"
-            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
-        }
+    }
+    src = mputstr(src,
+      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"string\");\n"
+      "    clean_up();\n"
+      "    return JSON_ERROR_FATAL;\n"
+      "  }\n"
+      "  case JSON_TOKEN_LITERAL_TRUE:\n"
+      "  case JSON_TOKEN_LITERAL_FALSE: {\n");
+    for (i = 0; i < sdef->nElements; ++i) {
+      if (JSON_BOOLEAN & sdef->elements[i].jsonValueType) {
+        src = mputprintf(src,
+          "    p_tok.set_buf_pos(buf_pos);\n"
+          "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
+          "    if (0 <= ret_val) {\n"
+          "      return ret_val;\n"
+          "    }\n"
+          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
       }
-      src = mputstr(src,
-        "    char* literal_str = mprintf(\"literal (%s)\",\n"
-        "      (JSON_TOKEN_LITERAL_TRUE == j_token) ? \"true\" : \"false\");\n"
-        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, literal_str);\n"
-        "    Free(literal_str);\n"
-        "    clean_up();\n"
-        "    return JSON_ERROR_FATAL;\n"
-        "  }\n"
-        "  case JSON_TOKEN_ARRAY_START: {\n");
-      for (i = 0; i < sdef->nElements; ++i) {
-        if (JSON_ARRAY & sdef->elements[i].jsonValueType) {
-          src = mputprintf(src,
-            "    p_tok.set_buf_pos(buf_pos);\n"
-            "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
-            "    if (0 <= ret_val) {\n"
-            "      return ret_val;\n"
-            "    }\n"
-            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
-        }
+    }
+    src = mputstr(src,
+      "    char* literal_str = mprintf(\"literal (%s)\",\n"
+      "      (JSON_TOKEN_LITERAL_TRUE == j_token) ? \"true\" : \"false\");\n"
+      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, literal_str);\n"
+      "    Free(literal_str);\n"
+      "    clean_up();\n"
+      "    return JSON_ERROR_FATAL;\n"
+      "  }\n"
+      "  case JSON_TOKEN_ARRAY_START: {\n");
+    for (i = 0; i < sdef->nElements; ++i) {
+      if (JSON_ARRAY & sdef->elements[i].jsonValueType) {
+        src = mputprintf(src,
+          "    p_tok.set_buf_pos(buf_pos);\n"
+          "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
+          "    if (0 <= ret_val) {\n"
+          "      return ret_val;\n"
+          "    }\n"
+          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
       }
-      src = mputstr(src,
-        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"array\");\n"
-        "    clean_up();\n"
-        "    return JSON_ERROR_FATAL;\n"
-        "  }\n"
-        "  case JSON_TOKEN_OBJECT_START: {\n");
-      for (i = 0; i < sdef->nElements; ++i) {
-        if (JSON_OBJECT & sdef->elements[i].jsonValueType) {
-          src = mputprintf(src,
-            "    p_tok.set_buf_pos(buf_pos);\n"
-            "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
-            "    if (0 <= ret_val) {\n"
-            "      return ret_val;\n"
-            "    }\n"
-            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
-        }
+    }
+    src = mputstr(src,
+      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"array\");\n"
+      "    clean_up();\n"
+      "    return JSON_ERROR_FATAL;\n"
+      "  }\n"
+      "  case JSON_TOKEN_OBJECT_START: {\n");
+    for (i = 0; i < sdef->nElements; ++i) {
+      if (JSON_OBJECT & sdef->elements[i].jsonValueType) {
+        src = mputprintf(src,
+          "    p_tok.set_buf_pos(buf_pos);\n"
+          "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
+          "    if (0 <= ret_val) {\n"
+          "      return ret_val;\n"
+          "    }\n"
+          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
       }
-      src = mputstr(src,
-        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"object\");\n"
-        "    clean_up();\n"
-        "    return JSON_ERROR_FATAL;\n"
-        "  }\n"
-        "  case JSON_TOKEN_LITERAL_NULL: {\n");
-      for (i = 0; i < sdef->nElements; ++i) {
-        if (JSON_NULL & sdef->elements[i].jsonValueType) {
-          src = mputprintf(src,
-            "    p_tok.set_buf_pos(buf_pos);\n"
-            "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
-            "    if (0 <= ret_val) {\n"
-            "      return ret_val;\n"
-            "    }\n"
-            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
-        }
+    }
+    src = mputstr(src,
+      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"object\");\n"
+      "    clean_up();\n"
+      "    return JSON_ERROR_FATAL;\n"
+      "  }\n"
+      "  case JSON_TOKEN_LITERAL_NULL: {\n");
+    for (i = 0; i < sdef->nElements; ++i) {
+      if (JSON_NULL & sdef->elements[i].jsonValueType) {
+        src = mputprintf(src,
+          "    p_tok.set_buf_pos(buf_pos);\n"
+          "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
+          "    if (0 <= ret_val) {\n"
+          "      return ret_val;\n"
+          "    }\n"
+          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
       }
-      src = mputstr(src,
-        "    clean_up();\n"
-        // the caller might be able to decode the null value if it's an optional field
-        // only return an invalid token error, not a fatal error
-        "    return JSON_ERROR_INVALID_TOKEN;\n"
-        "  }\n"
-        "  case JSON_TOKEN_ERROR:\n"
-        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
-        "    return JSON_ERROR_FATAL;\n"
-        "  default:\n"
-        "    return JSON_ERROR_INVALID_TOKEN;\n"
-        "  }\n"
-        "  return 0;\n"
-        "}\n\n");
-    } else { // not "as value"
+    }
+    src = mputstr(src,
+      "    clean_up();\n"
+      // the caller might be able to decode the null value if it's an optional field
+      // only return an invalid token error, not a fatal error
+      "    return JSON_ERROR_INVALID_TOKEN;\n"
+      "  }\n"
+      "  case JSON_TOKEN_ERROR:\n"
+      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
+      "    return JSON_ERROR_FATAL;\n"
+      "  default:\n"
+      "    return JSON_ERROR_INVALID_TOKEN;\n"
+      "  }\n"
+      "  return ret_val;\n");
+    if (!sdef->jsonAsValue) {
       src = mputprintf(src,
+        " }\n"
+        " else {\n" // if there is no 'as value' set in the type descriptor
         "  size_t dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n"
         "  if (JSON_TOKEN_ERROR == j_token) {\n"
         "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
@@ -2292,8 +2321,9 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
         "    return JSON_ERROR_FATAL;\n"
         "  }\n\n"
         "  return (int)dec_len;\n"
-        "}\n\n");
+        " }\n");
     }
+    src = mputstr(src, "}\n\n");
   }
 
   /* end of class definition */
diff --git a/core2/Basetype2.cc b/core2/Basetype2.cc
index 0d130b10354886230eff957f76c35db950560c75..3333a69af800fb184d7c116e7867e0ff9be61218 100644
--- a/core2/Basetype2.cc
+++ b/core2/Basetype2.cc
@@ -5758,6 +5758,12 @@ int Record_Type::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
     return -1;
   }
   
+  if (NULL != p_td.json && p_td.json->as_value) {
+    // if 'as value' is set, then the record/set has only one field,
+    // encode that without any brackets or field names
+    return get_at(0)->JSON_encode(*fld_descr(0), p_tok);
+  }
+  
   int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
   
   int field_count = get_count();
@@ -5786,7 +5792,7 @@ int Record_Type::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
 }
 
 int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
-                                     const TTCN_Typedescriptor_t& /*p_td*/,
+                                     const TTCN_Typedescriptor_t& p_td,
                                      JSON_Tokenizer& p_tok) const 
 {
   if (!is_bound()) {
@@ -5795,7 +5801,9 @@ int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
     return -1;
   }
   
-  int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+  boolean as_value = NULL != p_td.json && p_td.json->as_value;
+  
+  int enc_len = as_value ? 0 : p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
   
   int values_idx = 0;
   int edescr_idx = 0;
@@ -5809,7 +5817,7 @@ int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
     const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(i, values_idx);
     const Erroneous_descriptor_t* emb_descr = p_err_descr->next_field_emb_descr(i, edescr_idx);
     
-    if (NULL != err_vals && NULL != err_vals->before) {
+    if (!as_value && NULL != err_vals && NULL != err_vals->before) {
       if (NULL == err_vals->before->errval) {
         TTCN_error("internal error: erroneous before value missing");
       }
@@ -5836,16 +5844,20 @@ int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
             TTCN_error("internal error: erroneous before typedescriptor missing");
           }
           // only replace the field's value, keep the field name
-          enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, field_name);
+          if (!as_value) {
+            enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, field_name);
+          }
           enc_len += err_vals->value->errval->JSON_encode(*(err_vals->value->type_descr), p_tok);
         }
       }
     } else {
       boolean metainfo_unbound = NULL != fld_descr(i)->json && fld_descr(i)->json->metainfo_unbound;
       if ((NULL != fld_descr(i)->json && fld_descr(i)->json->omit_as_null) || 
-          get_at(i)->is_present() || metainfo_unbound) {
-        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, field_name);
-        if (metainfo_unbound && !get_at(i)->is_bound()) {
+          get_at(i)->is_present() || metainfo_unbound || as_value) {
+        if (!as_value) {
+          enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, field_name);
+        }
+        if (!as_value && metainfo_unbound && !get_at(i)->is_bound()) {
           enc_len += p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL);
           char* metainfo_str = mprintf("metainfo %s", field_name);
           enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, metainfo_str);
@@ -5860,7 +5872,7 @@ int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
       }
     }
     
-    if (NULL != err_vals && NULL != err_vals->after) {
+    if (!as_value && NULL != err_vals && NULL != err_vals->after) {
       if (NULL == err_vals->after->errval) {
         TTCN_error("internal error: erroneous after value missing");
       }
@@ -5881,12 +5893,19 @@ int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
     }
   }
   
-  enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+  if (!as_value) {
+    enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+  }
   return enc_len;
 }
 
-int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& /*p_td*/, JSON_Tokenizer& p_tok, boolean p_silent)
+int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
 {
+  if (NULL != p_td.json && p_td.json->as_value) {
+    // if 'as value' is set, then the record/set has only one field,
+    // decode that without the need of any brackets or field names 
+    return get_at(0)->JSON_decode(*fld_descr(0), p_tok, p_silent);
+  }
   json_token_t token = JSON_TOKEN_NONE;
   size_t dec_len = p_tok.get_next_token(&token, NULL, NULL);
   if (JSON_TOKEN_ERROR == token) {
diff --git a/regression_test/json/AttributeTestcases.ttcn b/regression_test/json/AttributeTestcases.ttcn
index 247a1e9fa8c278b4d486ef914d6751f46693ec63..b82b0c1ada8bb8af24f5b129b55053338c0dd8ec 100644
--- a/regression_test/json/AttributeTestcases.ttcn
+++ b/regression_test/json/AttributeTestcases.ttcn
@@ -352,6 +352,91 @@ testcase tc_attribute_metainfo_for_unbound_arrays() runs on MTC {
   f_bool2verdict( log2str(f_dec_meta_arr(os)) == log2str(arr) );
 }
 
+testcase tc_attribute_as_value_rec() runs on MTC {
+  var RecAsValue val := { field := 10 };
+  var bitstring enc_exp := oct2bit(char2oct("10"));
+  var bitstring enc := encvalue(val);
+  if (enc != enc_exp) {
+    setverdict(fail, "Encoding failed. Expected: ", enc_exp, ", got: ", enc);
+  }
+  else {
+    var RecAsValue dec;
+    var integer res := decvalue(enc, dec);
+    if (res != 0) {
+      setverdict(fail, "Decoding failed. Result: ", res);
+    }
+    else if (lengthof(enc) != 0) {
+      setverdict(fail, "Decoding failed. Remaining bits: ", enc);
+    }
+    else if (dec != val) {
+      setverdict(fail, "Decoding failed. Expected value: ", val, ", got: ", dec);
+    }
+    else {
+      setverdict(pass);
+    }
+  }
+}
+
+testcase tc_attribute_not_as_value_rec() runs on MTC {
+  var RecNotAsValue val := { field := { 1.0, 2.0 } };
+  var bitstring enc_exp := oct2bit(char2oct("{\"field\":[1.000000,2.000000]}"));
+  var bitstring enc := encvalue(val);
+  if (enc != enc_exp) {
+    setverdict(fail, "Encoding failed. Expected: ", enc_exp, ", got: ", enc);
+  }
+  else {
+    var RecNotAsValue dec;
+    var integer res := decvalue(enc, dec);
+    if (res != 0) {
+      setverdict(fail, "Decoding failed. Result: ", res);
+    }
+    else if (lengthof(enc) != 0) {
+      setverdict(fail, "Decoding failed. Remaining bits: ", enc);
+    }
+    else if (dec != val) {
+      setverdict(fail, "Decoding failed. Expected value: ", val, ", got: ", dec);
+    }
+    else {
+      setverdict(pass);
+    }
+  }
+}
+
+testcase tc_attribute_as_value_fields() runs on MTC {
+  var SetWithAsValueFields val := {
+    uni := { i := -3 },
+    rec := { field := { 1.0, 2.0 } },
+    list := {
+      { integer := 12 },
+      { charstring := "abc" },
+      { R := { i := 6, cs := "xy", b := false, d := Wednesday } },
+      { Thing := { bval := true } },
+      { RoI := { 1, 2, 3 } }
+    }
+  };
+  var bitstring enc_exp := oct2bit(char2oct("{\"uni\":-3,\"rec\":[1.000000,2.000000],\"list\":[12,\"abc\",{\"i\":6,\"cs\":\"xy\",\"b\":false,\"d\":\"Wednesday\"},true,[1,2,3]]}"));
+  var bitstring enc := encvalue(val);
+  if (enc != enc_exp) {
+    setverdict(fail, "Encoding failed. Expected: ", enc_exp, ", got: ", enc);
+  }
+  else {
+    var SetWithAsValueFields dec;
+    var integer res := decvalue(enc, dec);
+    if (res != 0) {
+      setverdict(fail, "Decoding failed. Result: ", res);
+    }
+    else if (lengthof(enc) != 0) {
+      setverdict(fail, "Decoding failed. Remaining bits: ", enc);
+    }
+    else if (dec != val) {
+      setverdict(fail, "Decoding failed. Expected value: ", val, ", got: ", dec);
+    }
+    else {
+      setverdict(pass);
+    }
+  }
+}
+
 
 control {
   execute(tc_NoAttributeOnUpperLevel())
@@ -372,5 +457,8 @@ control {
   execute(tc_attribute_metainfo_for_unbound_negtest());
   execute(tc_attribute_metainfo_for_unbound_empty_rec());
   execute(tc_attribute_metainfo_for_unbound_arrays());
+  execute(tc_attribute_as_value_rec());
+  execute(tc_attribute_not_as_value_rec());
+  execute(tc_attribute_as_value_fields());
 }
 }
diff --git a/regression_test/json/Types.ttcn b/regression_test/json/Types.ttcn
index d2953efc8a78aef9f8050671eda2ef066c2922bd..883317f52f3e51035c321ffad50807d5d9bb4070 100644
--- a/regression_test/json/Types.ttcn
+++ b/regression_test/json/Types.ttcn
@@ -264,6 +264,34 @@ with { variant "JSON: metainfo for unbound"; }
 type float MetainfoArray[3]
 with { variant "JSON: metainfo for unbound"; }
 
+type record RecAsValue {
+  integer field
+}
+with {
+  variant "JSON: as value";
+}
+
+type record RecNotAsValue {
+  RoF field
+}
+
+type union UniNotAsValue {
+  integer i,
+  octetstring o
+}
+
+type set SetWithAsValueFields {
+  UniNotAsValue uni,
+  RecNotAsValue rec,
+  record of anytype list
+}
+with {
+  variant (uni) "JSON: as value";
+  variant (rec) "JSON: as value";
+  variant (list[-]) "JSON: as value";
+}
+
 } with {
   encode "JSON";
+  extension "anytype integer, charstring, R, RoI, Thing";
 }
diff --git a/usrguide/referenceguide.doc b/usrguide/referenceguide.doc
index 3a9e5f1d399eb5adb8092cd43159fb570e210839..9ada0d4c31829ad79b26f6616abd3dbeaa0654c0 100644
Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ