We have a funny situation where we have a dataset with multiple tables, some nested. We use the same SERIALIZE-NAME on the nested tables to keep the format across the tables the same, but this seems to cause problems when doing a READ-JSON. READ-XML seems to work 100%.
A simplified test case - we have parent1 and parent2, each with its nested child1 and child2, but we use a serialize-name of child on both of them:
DEFINE TEMP-TABLE parent1 NO-UNDO SERIALIZE-NAME "parent1"
FIELD cID AS CHARACTER SERIALIZE-NAME "id"
FIELD cName AS CHARACTER SERIALIZE-NAME "name".
DEFINE TEMP-TABLE parent2 NO-UNDO SERIALIZE-NAME "parent2"
FIELD cID AS CHARACTER SERIALIZE-NAME "id"
FIELD cName AS CHARACTER SERIALIZE-NAME "name".
DEFINE TEMP-TABLE child1 NO-UNDO SERIALIZE-NAME "child"
FIELD cID AS CHARACTER SERIALIZE-HIDDEN
FIELD cValue AS CHARACTER SERIALIZE-NAME "value".
DEFINE TEMP-TABLE child2 NO-UNDO SERIALIZE-NAME "child"
FIELD cID AS CHARACTER SERIALIZE-HIDDEN
FIELD cValue AS CHARACTER SERIALIZE-NAME "value".
DEFINE DATASET dsTest SERIALIZE-NAME "test"
FOR parent1, child1, parent2, child2
DATA-RELATION pc1 FOR parent1, child1 RELATION-FIELD(cID, cID) NESTED
DATA-RELATION pc2 FOR parent2, child2 RELATION-FIELD(cID, cID) NESTED.
DEFINE VARIABLE lcData AS LONGCHAR NO-UNDO.
CREATE parent2.
ASSIGN
parent2.cID = "2"
parent2.cName = "parent2".
CREATE child2.
ASSIGN
child2.cID = "2"
child2.cValue = "test2".
DATASET dsTest:WRITE-JSON("longchar", lcData, TRUE).
MESSAGE STRING(lcData) VIEW-AS ALERT-BOX.
The JSON that comes back is
---------------------------
Message (Press HELP to view stack trace)
---------------------------
{"test": {
"parent2": [
{
"id": "2",
"name": "parent2",
"child": [
{
"value": "test2"
}
]
}
]
}}
---------------------------
OK Help
---------------------------
Now when I try to read this exact JSON back into the dataset it's not behaving:
DEFINE TEMP-TABLE parent1 NO-UNDO SERIALIZE-NAME "parent1"
FIELD cID AS CHARACTER SERIALIZE-NAME "id"
FIELD cName AS CHARACTER SERIALIZE-NAME "name".
DEFINE TEMP-TABLE parent2 NO-UNDO SERIALIZE-NAME "parent2"
FIELD cID AS CHARACTER SERIALIZE-NAME "id"
FIELD cName AS CHARACTER SERIALIZE-NAME "name".
DEFINE TEMP-TABLE child1 NO-UNDO SERIALIZE-NAME "child"
FIELD cID AS CHARACTER SERIALIZE-HIDDEN
FIELD cValue AS CHARACTER SERIALIZE-NAME "value".
DEFINE TEMP-TABLE child2 NO-UNDO SERIALIZE-NAME "child"
FIELD cID AS CHARACTER SERIALIZE-HIDDEN
FIELD cValue AS CHARACTER SERIALIZE-NAME "value".
DEFINE DATASET dsTest SERIALIZE-NAME "test"
FOR parent1, child1, parent2, child2
DATA-RELATION pc1 FOR parent1, child1 RELATION-FIELD(cID, cID) NESTED
DATA-RELATION pc2 FOR parent2, child2 RELATION-FIELD(cID, cID) NESTED.
DEFINE VARIABLE lcData AS LONGCHAR NO-UNDO.
lcData = '~{"test": ~{
"parent2": [
~{
"id": "2",
"name": "parent2",
"child": [
~{
"value": "test2"
~}
]
~}
]
~}~}'.
DATASET dsTest:READ-JSON("longchar", lcData).
FOR EACH parent1:
DISPLAY parent1. /* displays nothing, this is correct */
END.
FOR EACH child1:
DISPLAY child1. /* displays test2 with no id, this is wrong */
END.
FOR EACH parent2:
DISPLAY parent2. /* displays parent2, this is correct */
END.
FOR EACH child2:
DISPLAY child2. /* displays nothing, this is wrong */
END.
This looks like a bug to me. Anyone has an idea to get past this? We're using OE 11.7.4.
Hi,
It's actually not a bug, but I do agree that it's funny :).
You have defined the temp-table field to be serialize-hidden (FIELD cID AS CHARACTER SERIALIZE-HIDDEN), but ABL needs a value on that field to "link" to the parent temp-table record. Since you are not supplying it, it will just use the field default value, which does not help.
If you do want to use something like that in your json structure, you may want to use PARENT-ID-RELATION instead of DATA-RELATION, which will use a RECID to the parent record as a "link".
Clearly a bug imho, all relations are defined as nested so the parser should be able to know that a 'child' node inside 'parent2' is actually a 'child2' record and also set it's parent id even if set as serialize hidden. It seems to be confused by the serialize-name which is the same for both child tables, if you change the serialize-name for child2 and update the name in the json it will yield the correct results.
Even when making use of PARENT-ID-RELATION it's still misbehaving:
DEFINE TEMP-TABLE parent1 NO-UNDO SERIALIZE-NAME "parent1"
FIELD cName AS CHARACTER SERIALIZE-NAME "name".
DEFINE TEMP-TABLE parent2 NO-UNDO SERIALIZE-NAME "parent2"
FIELD cName AS CHARACTER SERIALIZE-NAME "name".
DEFINE TEMP-TABLE child1 NO-UNDO SERIALIZE-NAME "child"
FIELD rID AS RECID SERIALIZE-HIDDEN
FIELD cValue AS CHARACTER SERIALIZE-NAME "value".
DEFINE TEMP-TABLE child2 NO-UNDO SERIALIZE-NAME "child"
FIELD rID AS RECID SERIALIZE-HIDDEN
FIELD cValue AS CHARACTER SERIALIZE-NAME "value".
DEFINE DATASET dsTest SERIALIZE-NAME "test"
FOR parent1, child1, parent2, child2
PARENT-ID-RELATION pc1 FOR parent1, child1 PARENT-ID-FIELD rID
PARENT-ID-RELATION pc2 FOR parent2, child2 PARENT-ID-FIELD rID.
DEFINE VARIABLE lcData AS LONGCHAR NO-UNDO.
lcData = '~{"test": ~{
"parent2": [
~{
"id": "2",
"name": "parent2",
"child": [
~{
"value": "test2"
~}
]
~}
]
~}~}'.
DATASET dsTest:READ-JSON("longchar", lcData).
FOR EACH parent1:
DISPLAY parent1. /* displays nothing, this is correct */
END.
FOR EACH child1:
DISPLAY child1. /* displays test2 with unknown id, this is wrong */
END.
FOR EACH parent2:
DISPLAY parent2. /* displays parent2, this is correct */
END.
FOR EACH child2:
DISPLAY child2. /* displays nothing, this is wrong */
END.
Just noticed now that you are actually getting something on child1.
Darn...this is a bug.
I assume changing the serialize-name to 'child1' and 'child2' works even with the field rID set to serialize-hidden.
As a workaround, you could parse the json manually using Progress.Json.ObjectModel.* and create the needed records.
I've logged this with Progress Suppport: Case - 00499274