Yes - you probably already know that if a type implements json.Unmarshaler, it will be used when json.Unmarshal() is called with that type as the second parameter. The problem that often occurs is the need to unmarshal the receiver's type as part of the custom unmarshal code. This can be overcome in several ways, the most common of which is to use a local type to do the unmarshaling. You can save a lot of duplicate code with the judicious use of a type alias though.
I've updated your code above to stub out the types represented by Todo's fields as follows:
type Sub int
type ParsedTime struct {
Deadline time.Time
Created time.Time
}
type Todo struct {
ID int `json:"todo_id" db:"todo_id"`
Name string `json:"todo_name" db:"todo_name"`
UserID int `json:"user_id" db:"user_id"`
Subs []Sub `json:"subs" db:"subs"`
Times ParsedTime `json:"-" db:"times"`
}
Note that the only change of relevance is to ignore the Times field when `json.Unmarshal is called. I only changed the field names to get my IDE's linter to shut up! With these types, we can define a custom unmarshaler as follows:
func (t *Todo) UnmarshalJSON(data []byte) error {
type TodoJSON Todo
todo := struct {
*TodoJSON
Deadline string `json:"deadline"`
}{
TodoJSON: (*TodoJSON)(t),
}
if err := json.Unmarshal(data, &todo); err != nil {
return err
}
deadline, err := time.Parse(time.RFC3339, todo.Deadline)
if err != nil {
return err
}
t.Times.Deadline = deadline
return nil
}
There are two key techniques used in this code. First, using a type alias eliminates the infinite recursion that would occur if Todo was used directly. Second, creating a local type that embeds *Todo eliminates the need to completely retype the Todo type's fields - only the desired Deadline field needs to be added. I also assumed that Deadline was a time.Time to show that this code also allows the field to be processed before it's assigned (time.Parse()).
"missing destination name deadline"does not seem to be coming from the stdlib'sencoding/jsonpackage. Update your question to include the JSON. And also include the json-unmarshaling Go code that produces that specific error.sqlxpackage so I'm going to say you're correct!