Copy nested struct parsing some fields into other formats

Hi!,

Still struggling with some things since I’m new to go but pretty much excited because things are starting to work…

I’m working with some nested structs that cotain time.Time fields.
I want to marshal those structs as JSON to save them to a file, but I need to convert those time.Time fields as string because I don’t want the long date format that golang uses.
Therefore I need to convert those fields using time.Format("2006-01-02") and then marshal the struct.

This is my nested struct

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
}

Do I need to convert the struct to the type below, and then marshal it with json.Marshal?

type FlujoOut struct {
	Date     string
	Rate     float64
	Amort    float64
	Residual float64
	Amount   float64
}

type BondOut struct {
	ID        string
	Ticker    string
	IssueDate string
	Maturity  string
	Coupon    float64
	Cashflow  []FlujoOut
}

If true, how do I convert one struct to another considering it has a nested slice of struct inside?

Thanks in advance!!

How about

type Date time.Time
func (d Date) MarshalJSON() ([]byte,error) {
  return []byte(time.Time(d).Format("2006-01-0")),nil
}

and declare all the time.Time fields in your Flujo and Bond structs as Date?

You’d want an UnmarshalJSON method, too.

I start with a JSON file which contains the nested struct, but with the dates in "2006-01-02" format because the file is being populated by another (external) module.

Here an example:

{
    "ID": "1",
    "ticker": "S30J2",
    "issueDate": "2022-01-31",
    "maturity": "2023-06-30",
    "coupon": 0,
    "cashFlow": [
        {   "date": "2022-06-30",
            "rate": 0,
            "amortization": 1,
            "residual": 0,
            "amount": 50},
            {
            "date": "2023-06-30",
            "rate": 0,
            "amortization": 1,
            "residual": 0,
            "amount": 50}
    ]
}

I unmarshal them to the referred structures (Bond & Flujo) with this UnmarshalJSON methods.

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
	u.Cashflow = aux.Cashflow
	return nil
}

So now I have the JSON loaded to a struct.

When the API that I’m trying to write receives a new via the POST endpoint, which has to be added to the items contained in the struct, it receives the date in "2006-01-02" format. So I added to the struct, parsing it with the above UnmarshalJSON method.

After that I need to dump the struct to the file to preserve it. But I’m handling the dates as time.Time with the struct but need to write them in the file as "2006-01-02" again.

If I define ALL my structs with Date as you mentioned, the UnmarshallJSON doesn’t work.

I apologize If I couldn’t make myself more clear.

If you add an UnmarshalJSON method for *Date, then you shouldn’t need UnmarshalJSON for *Flujo and *Bond. Your UnmarshalJSONs are only there to parse the date text, but that should be done for you if the fields are Date.

1 Like

First things first: Thank you very much for your help!

Now I think I’m starting to get it right.

Dates are stored in wall: ext: loc: format when using custom types in structs. When printing out or saving them, I should format them using time.Time(var_Date).Format("2006-01-02").

Why is that when using custom types the value is stored in that way? Go Playground - The Go Programming Language

How can I print the whole struct and get the date formatted as "2006-01-02"?

Try providing a String() method for DateType that does formatting how you like.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.