Skip to content

Unmarshalling dict to struct #25

@lkramer

Description

@lkramer

Hey, I noticed that the function UnmarshalDict have some behaviour around field names that may be undesirable (certainly is for my usecase).

The main issue is that when it looks up a fieldname it will make the first character uppercase if necessary, but no further changes. That means that if a dict field uses snake case, like this:
this_is_a_field the corresponding field in a struct would have to be:

type MyStruct struct {
    This_is_a_field int
}

Which both brake go conventions and is also confusing.
For my own purpose I rewrote the function the following way:

func unmarshalResponse(t kdb.Dict) (*OrderResponse, error) {              
    var (
        keys = t.Key.Data.([]string)
        vals = t.Value.Data.([]*kdb.K)                                    
        v    = new(OrderResponse)                                         
    )
    vv := reflect.Indirect(reflect.ValueOf(v))                            
    for i := range keys {
        val := vals[i].Data
        fv := vv.FieldByName(strcase.ToCamel(keys[i]))                    
        if !fv.IsValid() {
            return nil, fmt.Errorf("field does not exist %q", keys[i])    
        }
        if fv.CanSet() && reflect.TypeOf(val).AssignableTo(fv.Type()) {   
            fv.Set(reflect.ValueOf(val))                                  
        }                                                                 
    }
    return v, nil                                                         
}                                                                         

It uses a thirdparty library to convert the name to CamelCase, but that could be done locally, I was just being lazy.
(an added benefit with this version is that it will error out if a correct struct field can not be found).

In addition it might be beneficial to support tags as an alternative to strict field naming similar to how the json marshalling works, so it would be possible to do something along these lines.

type MyStruct struct {
    Foo int `kdb:"this_is_a_field"`
}

I'm happy to write up a PR if you think this would be beneficial.

I'm also working on functionality to Marshal structs and maps into Dicts that might be useful as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions