YUK7HI
YUK7HI

Reputation: 13

Is there any advantage of using a closed record with a rest descriptor over an open record?

Consider the scenario where we create a record for capturing a JSON payload. (application/json content type) Is there any benefit of using a closed record with a JSON type rest descriptor over an open record?

Since JSON allows any primitive types and their derived array/record (object) assignment, and the record is only used for capturing a JSON payload, restricting it as a closed record seems redundant. (Only a few types like XML, query (SQL) will be restricted which cannot pass from application/json content)

E.g.:

type Person record {|
    string name;
    int age;
    json...;
|}

vs.

type Person record {
    string name;
    int age;
}

Upvotes: 1

Views: 61

Answers (2)

Sasindu Dilshara
Sasindu Dilshara

Reputation: 192

type Person record {|
    string name;
    int age;
    json...;
|};

type Person2 record {
    string name;
    int age;
};

public function main() {
    Person p = {name: "John", age: 30, "id": 1};
    Person2 p2 = {name: "John", age: 30, "id": 1};

    json id = p["id"]; // no need to cast
    json id2 = <json> p2["id"]; // If you need to derive the id field as a json, you have to cast it
}

Please consider the above code.

In here with the second type definition (open record), when you accessing the id field, you have to cast it into json.

In that kind of scenarios it will be better to use closed records with json rest descriptors.

Upvotes: 0

MaryamZi
MaryamZi

Reputation: 1304

Both of these are open records.

type Person record {
    string name;
    int age;
}

is equivalent to

type Person record {|
    string name;
    int age;
    anydata...;
|}

So the difference here is a rest descriptor of json vs anydata.

Having a more specific type is a better reflection of the possible values. Without the explicit rest descriptor (json...) the type says (additional/rest) field values can be anydata (therefore, can be table and xml too), but that isn't the case here.

With just response data binding to extract only the specified fields, it wouldn't make much of a difference either way. But, if you need to use Person in a context that expects a json value, if you open it with anydata, you'll have to do an extra conversion, which can be expensive.

E.g.,

import ballerina/http;

type E1 record {
    int id;
    string name;
};

type E2 record {|
    int id;
    string name;
    json...;
|};

// http:Request.setJsonPayload expects a `json` value as the argument

function f1(http:Request req, E1 e1) {
    req.setJsonPayload(e1); // error
    req.setJsonPayload(e1.toJson()); // OK, but needs a conversion
}

function f2(http:Request req, E2 e2) {
    req.setJsonPayload(e2); // OK, without a conversion
}

Upvotes: 2

Related Questions