Dokksen
Dokksen

Reputation: 430

joining two json objects using query expression in Ballerina

I have problem in joining two json objects with the integrated query language of Ballerina. I have two subservices, which responses with json objects on call. My goal is to join them based on a common key and return another json as result.

I have tried this code, but no success:

function getAllTransactionsPerDcr(string requestedContentType) returns json|xml|error {
   var dcrRequest = dcrService -> get("/dataControlRecords");
   var traRequest = traService -> get("/transactions");

   if (dcrRequest is http:Response && traRequest is http:Response){
       json|error dcrs = dcrRequest.getJsonPayload();
       json|error tras = traRequest.getJsonPayload();

       if(dcrs is json && tras is json ){
           if(requestedContentType == "application/json"){
              json output = from var dcr in <json[]>dcrs
                            join var tra in <json[]>tras
                            on <string>dcr.CDCRID equals <string>tra.CDCRID
                            select {
                                id: check dcr.CDCRID,
                                source: check dcr.VCSOURCES,
                                target: check dcr.VCTARGETS,
                                transactionId: check tra.CTRAID
                            };
              return output;
          }
      }
  }
}

And this is the ressource function:

@http:ResourceConfig {
    methods: ["GET"],
    path:"/data-control-records"
}
resource function getAllTransactionsPerDcr(http:Caller caller, http:Request request) returns error?{
    http:Response response = new;
    var result = getAllTransactionsPerDcr(request.getHeader("Accept"));
    if(result is json){
      check caller -> respond(result);  
    } else if (result is error){
        response.setTextPayload(result.message());
    }
}

I get the following error, if I call the service:

error: {ballerina}StackOverflow
    at ballerina.lang_query.0_0_1._InitFunction:process(types.bal:137)
       ballerina.lang_query.0_0_1._InputFunction:process(types.bal:197)
       ballerina.lang_query.0_0_1._StreamPipeline:next(types.bal:74)
       ballerina.lang_query.0_0_1._InnerJoinFunction:process(types.bal:355)
       ballerina.lang_query.0_0_1._InnerJoinFunction:process(types.bal:361)
       ........

The query works without the join clause, so there is something wrong with the join.

What could be the problem? Is it the right way to join json or is there a better way to do it?

Edit: Example data to reproduce the error:

dcrs:

[
  {
    "CDCRID": "D1234567",
    "VCSOURCES": "EXAMPLE SOURCE",
    "VCDATATYPS": "example",
    "VCDATATYPL": "example",
    "VCTARGETS": "EXAMPLE TARGET",
    "VCDESCL": "Lorem ipsum dolor sit amet"       
  },
  {
    "CDCRID": "D3456789",
    "VCSOURCES": "EXAMPLE SOURCE 2",
    "VCDATATYPS": "example2",
    "VCDATATYPL": "example2",
    "VCTARGETS": "EXAMPLE TARGET2",
    "VCDESCL": "Lorem ipsum dolor sit amet2"       
  }
]

tras:

[
  {
    "CTRAID": "T123456",
    "DTIMEOUT": "2020-06-29T08:40:07.000+02:00",
    "DTIMEIN": "2020-06-29T08:40:05.000+02:00",
    "CDCRID": "D1234567"
  },
  {
    "CTRAID": "T345678",
    "DTIMEOUT": "2020-06-29T08:40:07.000+02:00",
    "DTIMEIN": "2020-06-29T08:40:05.000+02:00",
    "CDCRID": "D3456789"
  }
]

Upvotes: 2

Views: 224

Answers (1)

Dulaj Dilshan
Dulaj Dilshan

Reputation: 170

I have tried this within a function initializing json values within the function body. Here, you can do this simply with join and from clauses.

import ballerina/io;

public function main() returns error? {
    json dcrs = [
        {
            "CDCRID": "D1234567",
            "VCSOURCES": "EXAMPLE SOURCE",
            "VCDATATYPS": "example",
            "VCDATATYPL": "example",
            "VCTARGETS": "EXAMPLE TARGET",
            "VCDESCL": "Lorem ipsum dolor sit amet"
        },
        {
            "CDCRID": "D3456789",
            "VCSOURCES": "EXAMPLE SOURCE 2",
            "VCDATATYPS": "example2",
            "VCDATATYPL": "example2",
            "VCTARGETS": "EXAMPLE TARGET2",
            "VCDESCL": "Lorem ipsum dolor sit amet2"
        }
    ];

    json tras = [
        {
            "CTRAID": "T123456",
            "DTIMEOUT": "2020-06-29T08:40:07.000+02:00",
            "DTIMEIN": "2020-06-29T08:40:05.000+02:00",
            "CDCRID": "D1234567"
        },
        {
            "CTRAID": "T345678",
            "DTIMEOUT": "2020-06-29T08:40:07.000+02:00",
            "DTIMEIN": "2020-06-29T08:40:05.000+02:00",
            "CDCRID": "D3456789"
        }
    ];

    json[] output = from var dcr in <json[]>dcrs
        join var tra in <json[]>tras on dcr.CDCRID equals tra.CDCRID
        select {
            id: check dcr.CDCRID,
            'source: check dcr.VCSOURCES,
            target: check dcr.VCTARGETS,
            transactionId: check tra.CTRAID
        };

    io:println(output);
}

Here, one thing to note is since source is a reserved keyword in Ballerina Swan Lake, we have to use 'source (with escape)

My output looks like the following.

[{"id":"D1234567","source":"EXAMPLE SOURCE","target":"EXAMPLE TARGET","transactionId":"T123456"},{"id":"D3456789","source":"EXAMPLE SOURCE 2","target":"EXAMPLE TARGET2","transactionId":"T345678"}]

Side note: Please check the latest way of defining resource functions with the Ballerina Swan Lake's latest syntax. (https://ballerina.io/learn/by-example/resource-methods/)

Here is an example you can refer.

Upvotes: 0

Related Questions