如何在 Ballerina 中使用带空格的 JSON 键名将 JSON 转换为记录或映射类型

问题描述

我从 [1] 获得了一个 JSON,由于 json 中键的命名,我无法直接使用在芭蕾舞演员中使用 JSON 的两种方法中的任何一种:
方法一:直接处理json值:

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

方法 2:使用特定于应用程序的、用户定义的 anydata 子类型:
无法使用 cloneWithType 或直接分配给用户定义的记录类型

我的解决方法是:

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);
}

我想知道是否有更好的方法来做到这一点?

解决方法

在 Ballerina 中处理 JSON 时,我更喜欢使用特定于应用程序的类型。您可以在 Ballerina 中使用带引号的标识符将完整的 json 负载映射到应用程序指定的类型。我使用查询表达式将堆栈数据条目过滤到数组中。还有其他一些略有变化的方法可以实现相同的目标。

请注意,我使用 Ballerina Swan Lake Alpha 3 来测试此代码。

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);
}