diff --git a/compiler2/Type.cc b/compiler2/Type.cc index 931068249e53f3d2c28c47ca2bb0bbcea7bc15cc..7510963c1103359ae74d24f5ac9574699638ef19 100644 --- a/compiler2/Type.cc +++ b/compiler2/Type.cc @@ -6087,7 +6087,9 @@ namespace Common { if (json_mem.has_key(t2)) { switch (*json_mem.get(t2)) { case ANSWER_YES: - // This field is OK, but we still need to check the others + case MISSING_ATTRIBUTE: + // This field is OK (or it's only missing an 'encode' + // attribute), but we still need to check the others case PROCESSING: // This type contains itself and is in the process // of being checked. Pretend it doesn't exist. @@ -6096,18 +6098,29 @@ namespace Common { // Avoids infinite recursion for self-referencing types. continue; case ANSWER_NO: - case MISSING_ATTRIBUTE: // One field is not OK => the structure is not OK return json_mem.remember(t, ANSWER_NO); } } else { json_mem.remember(t2, PROCESSING); - bool enabled = t2->has_encoding(CT_JSON); - json_mem.remember(t2, enabled ? ANSWER_YES : ANSWER_NO); - if (!enabled) { - // One field is not OK => the structure is not OK - return json_mem.remember(t, ANSWER_NO); + if (t2->has_encoding(CT_JSON)) { + // This field is OK + json_mem.remember(t2, ANSWER_YES); + } + else { + Type* t2_last = t2->get_type_refd_last(); + if (json_mem.has_key(t2_last) && + *json_mem.get(t2_last) == MISSING_ATTRIBUTE) { + // This field is missing an 'encode' attribute, otherwise + // it's OK + json_mem.remember(t2, MISSING_ATTRIBUTE); + } + else { + // One field is not OK => the structure is not OK + json_mem.remember(t2, ANSWER_NO); + return json_mem.remember(t, ANSWER_NO); + } } } } @@ -6120,24 +6133,38 @@ namespace Common { if (json_mem.has_key(t2)) { switch (*json_mem.get(t2)) { case ANSWER_YES: - // Continue checking + case MISSING_ATTRIBUTE: + // The element type is OK (or it's only missing an 'encode' + // attribute) case PROCESSING: // Recursive record-of. This is OK because the recursion // can always be broken with an empty record-of. break; case ANSWER_NO: - case MISSING_ATTRIBUTE: + // The element type is no OK => the structure is not OK return json_mem.remember(t, ANSWER_NO); break; } } else { json_mem.remember(t2, PROCESSING); - bool enabled = t2->has_encoding(CT_JSON); - json_mem.remember(t2, enabled ? ANSWER_YES : ANSWER_NO); - if (!enabled) { - // One field is not OK => the structure is not OK - return json_mem.remember(t, ANSWER_NO); + if (t2->has_encoding(CT_JSON)) { + // The element type is OK + json_mem.remember(t2, ANSWER_YES); + } + else { + Type* t2_last = t2->get_type_refd_last(); + if (json_mem.has_key(t2_last) && + *json_mem.get(t2_last) == MISSING_ATTRIBUTE) { + // The element type is missing an 'encode' attribute, + // otherwise it's OK + json_mem.remember(t2, MISSING_ATTRIBUTE); + } + else { + // The element type is no OK => the structure is not OK + json_mem.remember(t2, ANSWER_NO); + return json_mem.remember(t, ANSWER_NO); + } } } break; // check for an encode attribute diff --git a/regression_test/json/Functions.ttcn b/regression_test/json/Functions.ttcn index 40f0690e4b5de46262373e004cb14e39098112f7..7ca9708af6b7e4c94211347966822c1bc0b1a241 100644 --- a/regression_test/json/Functions.ttcn +++ b/regression_test/json/Functions.ttcn @@ -196,6 +196,12 @@ external function f_enc_embedded_enum(in UniWithEmbEncAttr.emb_list[-].en x) ret external function f_enc_embedded_any(in UniWithEmbEncAttr.emb_list[-].at_list[-] x) return octetstring with { extension "prototype(convert) encode(JSON)" } + +external function f_enc_multi_rec(in MultiLevelRec x) return octetstring + with { extension "prototype(convert) encode(JSON)" } + +external function f_enc_multi_list(in MultiLevelList x) return octetstring + with { extension "prototype(convert) encode(JSON)" } // for ASN.1 types external function f_enc_seqofint(in SeqOfInt x) return octetstring @@ -390,6 +396,12 @@ external function f_dec_embedded_enum(in octetstring x) return UniWithEmbEncAttr external function f_dec_embedded_any(in octetstring x) return UniWithEmbEncAttr.emb_list[-].at_list[-] with { extension "prototype(convert) decode(JSON)" } +external function f_dec_multi_rec(in octetstring x) return MultiLevelRec + with { extension "prototype(convert) decode(JSON)" } + +external function f_dec_multi_list(in octetstring x) return MultiLevelList + with { extension "prototype(convert) decode(JSON)" } + // for ASN.1 types external function f_dec_seqofint(in octetstring x) return SeqOfInt with { extension "prototype(convert) decode(JSON)" } diff --git a/regression_test/json/OtherTypes.ttcn b/regression_test/json/OtherTypes.ttcn index b55ebad06a57077ac4bf7174bc0889785da8b00f..9750148d595d7f24e2798ef60d9bbd0ecfcdf876 100644 --- a/regression_test/json/OtherTypes.ttcn +++ b/regression_test/json/OtherTypes.ttcn @@ -78,6 +78,27 @@ with { encode (emb_list[-].at_list[-]) "JSON"; } +type record of NotSuppEnum NotSuppRecOfEnum; + +type set NotSuppSet { + anytype at, + NotSuppList list +} + +type record MultiLevelRec { + NotSuppUni uni, + NotSuppRecOfEnum list, + NotSuppSet set_ +} +with { + encode "JSON"; +} + +type record of MultiLevelRec MultiLevelList +with { + encode "JSON"; +} + } with { extension "anytype integer, charstring" diff --git a/regression_test/json/Testcases.ttcn b/regression_test/json/Testcases.ttcn index 1c890c2626eab8ac414fa1883ac50779674437ac..28b86681e6e7f2c01393fb69ac104203486e6169 100644 --- a/regression_test/json/Testcases.ttcn +++ b/regression_test/json/Testcases.ttcn @@ -799,6 +799,31 @@ testcase tc_embedded_anytype() runs on MTC { f_bool2verdict(match(f_dec_embedded_any(os), x.emb_list[0].at_list[0])); } +const MultiLevelRec c_multi_rec := { + uni := { x := 1 }, + list := { val1 }, + set_ := { + at := { integer := 1 }, + list := { "abc", "xyz" } + } +} + +// Coding a record with JSON encoding, whose fields are (sometimes multi-level) structures with no JSON encoding support. +testcase tc_multi_level_record() runs on MTC { + var MultiLevelRec x := c_multi_rec; + var octetstring os := char2oct("{\"uni\":{\"x\":1},\"list\":[\"val1\"],\"set_\":{\"at\":{\"integer\":1},\"list\":[\"abc\",\"xyz\"]}}"); + f_check_encoding(encoded:= f_enc_multi_rec(x), expected := os); + f_bool2verdict(match(f_dec_multi_rec(os), x)); +} + +// Coding a record of with JSON encoding, whose elements are multi-level structures with no JSON encoding support. +testcase tc_multi_level_recordof() runs on MTC { + var MultiLevelList x := { c_multi_rec }; + var octetstring os := char2oct("[{\"uni\":{\"x\":1},\"list\":[\"val1\"],\"set_\":{\"at\":{\"integer\":1},\"list\":[\"abc\",\"xyz\"]}}]"); + f_check_encoding(encoded:= f_enc_multi_list(x), expected := os); + f_bool2verdict(match(f_dec_multi_list(os), x)); +} + //========================================================================= // Control //========================================================================= @@ -886,6 +911,8 @@ control { execute(tc_embedded_union()); execute(tc_embedded_enumerated()); execute(tc_embedded_anytype()); + execute(tc_multi_level_record()); + execute(tc_multi_level_recordof()); }