TL;DR
JSON types reference their value in memory, not the actual value. The below is snipped from https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/methods-auto/jsonobject/jsonobject-data-type

Be careful making JSON types equal to one another. When you do that you copy the reference, not the value. This caught me out.
Example 1
I’m implementing an interface which accepts a JsonObject parameter expecting that you will assign a value which will be used later on. The interface doesn’t require that the JsonObject is passed with var
. In fact, it requires that it isn’t. If you include var
the compiler will complain that you haven’t implemented all of the interface methods. Something like the JsonExample action in the below code.
“That’s never going to work, the parameter needs to be passed with var
” I thought. Better still, just have method return a JsonObject type. However, the interface probably pre-dates complex return types so we’ll let that go. Although, I think you could still return JSON types even before complex return types were introduced…but let it go.
pageextension 50100 "Customer List" extends "Customer List"
{
actions
{
addlast(processing)
{
action(JsonExample)
{
ApplicationArea = All;
trigger OnAction()
var
JsonExample: Codeunit "Json Example";
Object: JsonObject;
Result: Text;
begin
JsonExample.CalcJson(Object);
Object.WriteTo(Result);
Message(Result);
end;
}
action(JsonExample2)
{
ApplicationArea = All;
trigger OnAction()
var
JsonExample: Codeunit "Json Example";
Object: JsonObject;
Result: Text;
begin
JsonExample.CalcJson2(Object);
Object.WriteTo(Result);
Message(Result);
end;
}
action(JsonExample3)
{
ApplicationArea = All;
trigger OnAction()
var
JsonExample: Codeunit "Json Example";
Object: JsonObject;
Result: Text;
begin
JsonExample.CalcJson3(Object);
Object.WriteTo(Result);
Message(Result);
end;
}
}
}
}
codeunit 50100 "Json Example"
{
procedure CalcJson(Object: JsonObject)
begin
Object.Add('aKindOf', 'magic');
end;
procedure CalcJson2(Object: JsonObject)
var
CalcJson: Codeunit "Calc. Json";
begin
Object := CalcJson.CalcJson();
end;
procedure CalcJson3(Object: JsonObject)
var
CalcJson: Codeunit "Calc. Json";
JSON: Text;
begin
CalcJson.CalcJson().WriteTo(JSON);
Object.ReadFrom(JSON);
end;
}
codeunit 50101 "Calc. Json"
{
procedure CalcJson() Result: JsonObject
var
Boys: JsonObject;
begin
Boys.Add('backInTown', true);
Result.Add('boys', Boys);
end;
}
I was surprised that it did work. Call JsonExample and you get:
{"aKindOf":"magic"}
That’s because even without the var
keyword the JsonObject variable holds a refence to the object rather than the value itself, so it still exists after CalcJson()
has finished executing.
Example 2
OK, great. I went on to create a separate codeunit to handle the creation of the JsonObject. I wanted to add some error handling and separate the boilerplate of the interface implementation from the business logic.
I wrote something like CalcJson2()
. My tests started failing. It seemed that the JsonObject was empty. That puzzled me for a while. What had I done wrong? I think this is the problem.
- The JsonObject referenced by the
Result
variable in codeunit 50101 is created and has the properties added - This reference goes out of scope once
CalcJson
has finished executing and its value is lost/garbage collected/however it works in Business Central - The JsonObject referenced by the
Object
parameter is made equal to the first i.e. now points to the first JsonObject in memory – but that value has already gone - As the result the second JsonObject is empty when it is handed back to the calling code
Example 3
Instead of making the JSON types equal to one another explicitly copy the value of one to the other. Like this:
procedure CalcJson3(Object: JsonObject)
var
CalcJson: Codeunit "Calc. Json";
JSON: Text;
begin
CalcJson.CalcJson().WriteTo(JSON);
Object.ReadFrom(JSON);
end;
In this case writing the value of one to text and then reading it back in to the other. It looks a bit weird, but it works. JsonObject also has a Clone
method.
How to write this, please advise..
[
{
“transaction”: {
“Version”: “1.1”,
“TranDtls”: {
“TaxSch”: “GST”,
“SupTyp”: “B2B”,
“RegRev”: “Y”,
“EcmGstin”: “”,
“IgstOnIntra”: “N”
}
}
}
]
LikeLike