I am calling the AlphaVantage API that gives me this JSON response:
{
"Meta Data": {
"1. Information": "Intraday (5min) open, high, low, close prices and volume",
"2. Symbol": "IBM",
"3. Last Refreshed": "2024-04-19 19:55:00",
"4. Interval": "5min",
"5. Output Size": "Compact",
"6. Time Zone": "US/Eastern"
},
"Time Series (5min)": {
"2024-04-19 19:55:00": {
"1. open": "181.5200",
"2. high": "181.5800",
"3. low": "181.4600",
"4. close": "181.5100",
"5. volume": "158"
},
"2024-04-19 19:40:00": {
"1. open": "181.2000",
"2. high": "181.2000",
"3. low": "181.2000",
"4. close": "181.2000",
"5. volume": "27"
},
"2024-04-19 19:30:00": {
"1. open": "181.5600",
"2. high": "181.5600",
"3. low": "181.5600",
"4. close": "181.5600",
"5. volume": "20"
},
"2024-04-19 19:25:00": {
"1. open": "181.5600",
"2. high": "181.5600",
"3. low": "181.5600",
"4. close": "181.5600",
"5. volume": "1"
},...
}
}
I am trying to extract the data and store it in a object using a interface:
type IntradayInterface = {
metaData: MetaData;
interval: { [time: string]: IntervalData };
}
export type MetaData = {
information: string;
symbol: string;
lastRefreshed: Date;
interval: string;
outputSize: string;
timeZone: string;
}
export type IntervalData = {
open: string;
high: string;
low: string;
close: string;
volume: string;
}
export default IntradayInterface;
And here's my parser function:
function parseIntradayData(jsonData: any) : IntradayInterface {
const metaData = jsonData['Meta Data'];
let parsedMetaData : MetaData = {
information: metaData['1. Information'],
symbol: metaData['2. Symbol'],
lastRefreshed: metaData['3. Last Refreshed'],
interval: metaData['4. Interval'],
outputSize: metaData['5. Output Size'],
timeZone: metaData['6. Time Zone']
};
const intervalData = jsonData['Time Series (5min)'];
let parsedIntervalData: IntervalData = {
open: intervalData['1. open'],
high: intervalData['2. high'],
low: intervalData['3. low'],
close: intervalData['4. close'],
volume: intervalData['5. volume']
}
const returnData: IntradayInterface = {
metaData: parsedMetaData,
interval: intervalData
}
return returnData;
}
export default parseIntradayData;
The goal is to extract the data from the JSON response and store it in an object of type IntradayInterface
but the object is not populated correctly when I try. I have two assumptions:
1 - My Interface isn't setup correctly, specifically the interval
definition. I want to be able to also store each datetime that maps to the IntervalData
but I don't know how
2 - I am not parsing the interval "(Time Series 5min)" part of the JSON correctly
Any help with this would be greatly appreciated!
The "Time Series (5min)"
object in your input data has some nested objects, which you also want to transform. So you have to iterate over all of them
function parseIntradayData(jsonData: any) : IntradayInterface {
const metaData = jsonData['Meta Data'];
const parsedMetaData : MetaData = {
information: metaData['1. Information'],
symbol: metaData['2. Symbol'],
lastRefreshed: metaData['3. Last Refreshed'],
interval: metaData['4. Interval'],
outputSize: metaData['5. Output Size'],
timeZone: metaData['6. Time Zone']
};
const intervalData: Record<string, object> = jsonData['Time Series (5min)']; //hint a type here, so
const parsedIntervalData = Object.fromEntries(Object.entries<any>(intervalData).map(([k,v]) => {
let t = {
open: v['1. open'],
high: v['2. high'],
low: v['3. low'],
close: v['4. close'],
volume: v['5. volume']
};
return [k, t];
}));
const returnData: IntradayInterface = {
metaData: parsedMetaData,
interval: parsedIntervalData
}
return returnData;
}
Object.entries
transforms an object into an array of [key,value]
pairs. Then you can iterate over this array to transform your values. Finaly, Object.fromEntries
transforms the resulting [key,value]
pairs back to an object.
And looking at the mapping of the IntervalData
you can probably make that even simpler
let t = Object.fromEntries(Object.entries(v).map(([kk, vv]) => [kk, vv.split(" ")[1]])) as IntervalData;
because the mapping of the property names is just done by removing the 1.
, 2.
... from the property name. But as Object.fromEntries
does not infer any typ
Something similar could probably also be done with the MetaData
object.