deckarep / golang-set

A simple, battle-tested and generic set type for the Go language. Trusted by Docker, 1Password, Ethereum and Hashicorp.
Other
4k stars 272 forks source link

unmarshal json fails when set is part of struct #135

Closed hujun-open closed 3 months ago

hujun-open commented 3 months ago

it seems json umarshal fails when Set is part of struct, following code produces following error. not sure what did I miss here

I am using github.com/deckarep/golang-set/v2 v2.6.0 and go v1.22.1

{"MapSet":["init"],"Name":"test"}
panic: json: cannot unmarshal array into Go struct field TSet.MapSet of type mapset.Set[string]

code:

package main

import (
    "encoding/json"
    "fmt"

    mapset "github.com/deckarep/golang-set/v2"
)

type TSet struct {
    MapSet mapset.Set[string]
    Name   string
}

func main() {
    s1 := TSet{
        MapSet: mapset.NewSet("init"),
        Name:   "test",
    }
    buf, err := json.Marshal(s1)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(buf))
    s2 := new(TSet)
    err = json.Unmarshal(buf, s2)
    if err != nil {
        panic(err)
    }
    fmt.Printf("%+v\n", *s2)
}
clarkedb commented 3 months ago

This is a duplicate of #122 . See @deckarep's comment https://github.com/deckarep/golang-set/issues/122#issuecomment-1872382278 for a full explanation of why this is currently happening, but the short story is that the UnmarshalJSON function is not defined on the set with a pointer receiver.

As a workaround for now you can add s2.MapSet = mapset.NewSet[string]() after you declare s2 and it seems to work as you can see here: https://go.dev/play/p/NQcs2bSLCR2.

That's not ideal, but it will work for now until the open questions in #122 are resolved.

hujun-open commented 3 months ago

ok, thanks, the workaround works; though it would be nicer to fix this