Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom types unmarshal fails #156

Open
vickyramachandra opened this issue Oct 3, 2018 · 4 comments
Open

Custom types unmarshal fails #156

vickyramachandra opened this issue Oct 3, 2018 · 4 comments

Comments

@vickyramachandra
Copy link

Hey there,
If i have a struct like this

type Blog struct {
	Id json.Number `jsonapi:"primary,blogs"` // json.Number has unmarshal() impl in encoding/json
}

The value for id will not be mapped into the field. So any custom types which has their own marshal or unmarshal implementation doesn't work!

@mkarlesky
Copy link

First of all, thanks for this library. Very helpful.

I believe I'm running into the same problem as @vickyramachandra. I need to unmarshal a timestamp encoded as a string. The situation is virtually identical to the example shown in the Custom types section of the README. However, upon unmarshaling with UnmarshalManyPayload() I receive the error “json: cannot unmarshal string into Go value of type map[string]interface {}.” As far as I can tell the custom un/marshaling implementation is never called; the failure occurs before reaching that stage of unpacking the JSON API contents.

type Timestamp struct {
    time.Time
}

type downtime struct {
    Id           int           `jsonapi:"primary,downtimes"`
    Reason       string        `jsonapi:"attr,Reason"`
    Source       string        `jsonapi:"attr,Source"`
    Expiration   Timestamp     `jsonapi:"attr,Expiration"`
}

func (t *Timestamp) UnmarshalJSON(buf []byte) error {
    var err error
    t.Time, err = time.Parse(time.RFC3339, string(buf))
    return err
}

func (t *Timestamp) MarshalJSON() ([]byte, error) {
    return t.Time.MarshalText() // RFC 3339
}

@botverse
Copy link

botverse commented Oct 12, 2018

@shwoodard 's commit 3c8221b seem to have broken it.

func handleStruct(
	attribute interface{},
	fieldValue reflect.Value) (reflect.Value, error) {
        ...
	if err := json.Unmarshal(data, &node.Attributes); err != nil {
		return reflect.Value{}, err
	}
        ....
}

As in there, ^ node.Attributes is always a map[string]interface {}, before it was err = json.Unmarshal(data, model.Interface()) so the type was inferred from the field. Sorry I'm not confident enough with go to be able to submit a pr myself.

EDIT:

Heads up: It seems that that commit is not in sequence with the previous commit in master chronologically and that it comes from a different branch, so previous commit does not have a working implementation of custom fields either. I'm using parent commit 8b7e0bc from March which has custom types working but not nested attrs working, a workaround is to add json:"fieldname" to all the tags of the nested models.

@mkarlesky
Copy link

Thank you for the excellent investigative work, @botverse. If I must I think I can get by with the March commit until this issue is resolved.

@henrmota
Copy link

in this pull request #163

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants