naoina / toml

TOML parser and encoder library for Golang
MIT License
294 stars 50 forks source link

unmarshalTOML function not called #6

Closed adejoux closed 9 years ago

adejoux commented 9 years ago

Hello, Thanks for your great library.

I would like to setup default values for my structure

// A Row is a dashboard Row it can contains multiple panels
type Row struct {
    Collapse bool    `json:"collapse"`
    Editable bool    `json:"editable"`
    Height   string  `json:"height"`
    Panels   []Panel `json:"panels" toml:"panel"`
    Title    string  `json:"title"`
}

So I defined this method :

func (row *Row) UnmarshalTOML(b interface{}) error {
    fmt.Printf("toto\n") //for debug

    r := NewRow()
    err := toml.Unmarshal(b.([]byte), &r)
    *row = r
    return err
}

But the method is not called when I do a toml.Unmarshal call.

Do you have any ideas about what I could do wrong here ?

Thanks,

Alain

naoina commented 9 years ago

@adejoux

You don't implement the toml.Unmarshal interface. The correct signature of UnmarshalTOML is following.

UnmarshalTOML([]byte) error

But you defined

UnmarshalTOML(b interface{}) error

See also: https://github.com/naoina/toml#using-tomlunmarshaltoml-interface https://github.com/naoina/toml/blob/master/decode.go#L83

adejoux commented 9 years ago

You are right but it's still not solving my issue :

func (row *Row) UnmarshalTOML(data []byte) error {
    fmt.Printf("toto\n") //debug
    os.Exit(1) //debug

    r := NewRow()
    err := toml.Unmarshal(data, &r)
    if err != nil {
        return err
    }
    *row = r
    return err
}

It's called like that :

if err := toml.Unmarshal(buf, &row); err != nil {
        panic(err)
    }

    fmt.Println(row)
naoina commented 9 years ago

Sorry, I had misread your code. Row is a top-level struct, currently, UnmarshalTOML will apply against fields of struct. However, this behavior is different with encoding/json's Unmarshal, so I will fix it later.

adejoux commented 9 years ago

Oh ok. So it's why :) thanks for the explanation.

This behavior would work for me. I would be happy if I can encapsulate a Row struct in a Dashboard struct and having UnmarshalTOML called on Row when unmarshalling Dashboard.

// A Dashboard contains the Dashboard structure.
type Dashboard struct {
    Rows            []Row         `json:"rows" toml:"row"`
}

type Row struct {
    Collapse bool    `json:"collapse"`
    Editable bool    `json:"editable"`
    Height   string  `json:"height"`
    Panels   []Panel `json:"panels" toml:"panel"`
    Title    string  `json:"title"`
}

func (row *Row) UnmarshalTOML(data []byte) error {
    fmt.Printf("toto\n") //debug
    os.Exit(1) //debug

    r := NewRow()
    err := toml.Unmarshal(data, &r)
    if err != nil {
        return err
    }
    *row = r
    return err
}

And calling the unmarshal directly on dashboard :


func ConvertTemplate(file string) (dashboard Dashboard, err error) {

...

f err := toml.Unmarshal(buf, &dashboard); err != nil {
        panic(err)
    }

    fmt.Println(dashboard)
}

But it's not happening. I read your file test_decode.go and decode.go and I really don't understand what I am missing here.

Thanks

naoina commented 9 years ago

@adejoux

I have added encoding/json's Unmarshal-like behavior to UnmarshalTOML. You can try it in your code using latest master branch.

Thanks.