Reputation: 527
isolated function mockFunction(record {|string operation; float operand1; float operand2;|} input) returns string{
return "mockFunction scuccessful";
}
public function main() returns error? {
string input = "{\"operation\":\"ADDITION\",\"operand1\":23.0,\"operand2\":43.0}";
map<json> & readonly inputJson = check input.fromJsonStringWithType();
any|error observation = function:call(mockFunction, inputJson);
io:println(observation);
}
I got the following error when I tried the above.
error: {ballerina/lang.function}IncompatibleArguments {"message":"arguments of incompatible types: argument list '(map<(json & readonly)> & readonly)' cannot be passed to function expecting parameter list '(ai.agent:record {| string operation; float operand1; float operand2; |})'"}
Upvotes: 0
Views: 21
Reputation: 527
function:call()
method will attempt to cast the inputJson
to the expected argument type. It gives the above error when the casting fails.
fromJsonStringWithType
https://lib.ballerina.io/ballerina/lang.value/0.0.0#fromJsonStringWithType is a combination of fromJsonString
and fromJsonWithType
. Numbers are generally converted to decimal with fromJsonString
https://lib.ballerina.io/ballerina/lang.value/0.0.0#fromJsonString.
Numbers in the JSON string are converted into Ballerina values of type decimal except in the following two cases: if the JSON number starts with - and is numerically equal to zero, then it is converted into float value of -0.0; otherwise, if the JSON number is syntactically an integer and is in the range representable by a Ballerina int, then it is converted into a Ballerina int. A JSON number is considered syntactically an integer if it contains neither a decimal point nor an exponent.
Therefore, in this case, operand1
and operand2
are decimal
and not float
. This is why the cast fails.
io:println(inputJson is record {|string operation; float operand1; float operand2;|}); // false
io:println(inputJson is record {|string operation; decimal operand1; decimal operand2;|}); // true
The solution is to provide the exact type when doing the fromJsonStringWithType
record {|string operation; float operand1; float operand2;|} inputRecord = check input.fromJsonStringWithType();
fromJsonStringWithType
will creates a new value doing the numeric conversions, not a cast. Here the fromJsonString
step will still result in decimal
values for these fields, but the fromJsonWithType
step will handle the numeric conversion when cloning.
Upvotes: 0