Hi, I’m new to Golang. I’m doing my first steps with it writing a simple API that calculates and returns prices and IRR of some country-specific bonds.
I have a json file with the info for every bond. This is the json example file:
[
{
"ID": "1",
"ticker": "GD30",
"issueDate": "2020-01-01",
"maturity": "2030-07-09",
"coupon": 0.05,
"cashFlow": [
{ "date": "2021-01-09",
"rate": 0.00125,
"amortization": 0,
"residual": 1,
"amount": 0},
{ "date": "2021-07-09",
"rate": 0.00125,
"amortization": 0,
"residual": 1,
"amount": 0},
{ "date": "2022-01-09",
"rate": 0.005,
"amortization": 0,
"residual": 1,
"amount": 0}]
}
]
Since dates are written in "2006-01-02"
format, I need to parse them to time.Time
Therefore I’ve written a method to be called when unmarshaling the json in order to handle the date format.
This is the code that parses the JSON data.
package main
import (
"encoding/json"
"fmt"
"time"
)
const data = `[
{
"ID": "1",
"ticker": "GD30",
"issueDate": "2020-01-01",
"maturity": "2030-07-09",
"coupon": 0.05,
"cashFlow": [
{ "date": "2021-01-09",
"rate": 0.00125,
"amortization": 0,
"residual": 1,
"amount": 0},
{ "date": "2021-07-09",
"rate": 0.00125,
"amortization": 0,
"residual": 1,
"amount": 0},
{ "date": "2022-01-09",
"rate": 0.005,
"amortization": 0,
"residual": 1,
"amount": 0}]
}
]`
// define data structure to hold the json data
type Flujo struct {
Date time.Time
Rate float64
Amort float64
Residual float64
Amount float64
}
type Bond struct {
ID string
Ticker string
IssueDate time.Time
Maturity time.Time
Coupon float64
Cashflow []Flujo
}
const dateFormat = "2006-01-02"
var Bonds []Bond
func (c *Flujo) UnmarshalJSON(p []byte) error {
var aux struct {
Date string `json:"date"`
Rate float64 `json:"rate"`
Amort float64 `json:"amortization"`
Residual float64 `json:"residual"`
Amount float64 `json:"amount"`
}
err := json.Unmarshal(p, &aux)
if err != nil {
return err
}
t, err := time.Parse(dateFormat, aux.Date)
if err != nil {
return err
}
(*c).Date = t
(*c).Rate = aux.Rate
(*c).Amort = aux.Amort
(*c).Residual = aux.Residual
(*c).Amount = aux.Amount
return nil
}
func (u *Bond) UnmarshalJSON(p []byte) error {
var aux struct {
ID string `json:"id"`
Ticker string `json:"ticker"`
IssueDate string `json:"issueDate"`
Maturity string `json:"maturity"`
Coupon float64 `json:"coupon"`
Cashflow []Flujo `json:"cashFlow"`
}
err := json.Unmarshal(p, &aux)
if err != nil {
return err
}
t, err := time.Parse(dateFormat, aux.IssueDate)
if err != nil {
return err
}
y, err := time.Parse(dateFormat, aux.Maturity)
if err != nil {
return err
}
(*u).ID = aux.ID
(*u).Ticker = aux.Ticker
(*u).IssueDate = t
(*u).Maturity = y
(*u).Coupon = aux.Coupon
return nil
}
func main() {
// json data
// unmarshall the JSON
err := json.Unmarshal([]byte(data), &Bonds)
if err != nil {
fmt.Println("error:", err)
}
fmt.Println("Bonds: ", Bonds)
fmt.Println("Cashflow: ", Bonds[0].Cashflow)
}
The problem that I got is that the method of the inner struct is not mapping the data into the inner struct.
See the output:
Bonds: [{1 GD30 2020-01-01 00:00:00 +0000 UTC 2030-07-09 00:00:00 +0000 UTC 0.05 []}]
Cashflow: []
The Cashflow should have the 3 dates, rate, amortization and so on…
Any guess why the method is not mapping the data to the inner struct?
This is the link to a playground version of the code: Go Playground - The Go Programming Language
Thanks!