Suleka_28
Suleka_28

Reputation: 2909

How to Convert JSON to record or map type in Ballerina with JSON key names with spaces

I'm getting a JSON from [1], due to the naming of the keys in the json I was unable to straightaway use either of the 2 approches in hadling JSON in ballerina:
Approach 1: Work with json values directly:

string s = check j.x.y.z;

Approach 2: Work with application-specific, user-defined subtype of anydata:
couldn't use cloneWithType or directly assign to a user defined record type

My workaround was:

type AllStockData record {
    string open;
    string high;
    string low;
    string close;
    string volume;
};
AllStockData[] stockData = [];

public function main() returns @tainted  error? {

http:Client httpClient = check new ("https://www.alphavantage.co");
json jsonPayload = check httpClient->get("/query?function=TIME_SERIES_INTRADAY&symbol="+searchSymbol.toUpperAscii()+"&interval=5min&apikey="+apiKey, targetType = json);

map<json> allData = <map<json>>jsonPayload;
foreach json item in <map<json>>allData["Time Series (5min)"] {
    map<json> stockItem = <map<json>>item;
    AllStockData stock = { 
        open: stockItem["1. open"].toString(), 
        high: stockItem["2. high"].toString(), 
        low:  stockItem["3. low"].toString(),
        close: stockItem["4. close"].toString(), 
        volume: stockItem["5. volume"].toString()
    };
    stockData.push(stock);
}

I was wondering If there is a better way to do this?

Upvotes: 4

Views: 905

Answers (1)

Sameera Jayasoma
Sameera Jayasoma

Reputation: 1610

I prefer to work with application-specific types when dealing with JSON in Ballerina. You can use quoted identifiers in Ballerina to map the complete json payload into an application-specify type. I've used a query expression to filter out stack data entries into an array. There are other ways with slight variations to achieve the same thing.

Note that I've used Ballerina Swan Lake Alpha 3 to test this code.

import ballerina/io;
import ballerina/http;

type StockQuery record {|
    MetaData 'Meta\ Data;
    TimeSeries5min 'Time\ Series\ \(5min\);
|};

type MetaData record {|
    string '1\.\ Information;
    string '2\.\ Symbol;
    string '3\.\ Last\ Refreshed;
    string '4\.\ Interval;
    string '5\.\ Output\ Size;
    string '6\.\ Time\ Zone;
|};

type TimeSeries5min record {|
    StockData...;
|};

type StockData record {|
    string '1\.\ open;
    string '2\.\ high;
    string '3\.\ low;
    string '4\.\ close;
    string '5\.\ volume;
|};

public function main() returns error? {
    http:Client httpClient = check new ("https://www.alphavantage.co");
    json jsonPayload = check httpClient->get("/query?function=TIME_SERIES_INTRADAY&symbol=IBM&interval=5min&apikey=demo", 
targetType = json);

    StockQuery stockQuery = check jsonPayload.cloneWithType(StockQuery);
    TimeSeries5min timeSeries = stockQuery.Time\ Series\ \(5min\);
    StockData[] stockDataArr = from var key in timeSeries.keys()
                               let StockData? stockData = timeSeries[key]
                               where stockData is StockData
                               select stockData;

    io:println(stockDataArr);
}

Upvotes: 4

Related Questions