2

I'm want to use a custom type which is not exported and define an interface to use it. The custom type will implement the interface and everything works fine except for unmarshaling from JSON.

I created an example to explain it better:

type (
    Value interface {
        Set(k, v string)
    }

    value map[string]string
)

func New() Value {
    return value{}
}

func (val value) Set(k, v string) {
    val[k] = v
}

This approach will not provide direct access to the map and force the usage of New() function to create objects of type "Value".

When trying to unmarshal in an object created with New() I'm getting the error:

Failed to unmarshal value json: cannot unmarshal object into Go value of type main.Value

That can be fixed by making New() return "value" instead of "Value" but will still be a problem when trying to unmarshal an object like:

Storage struct {
        Val Value `json:"val"`
}

Any suggestions? Implementing Unmarshaler doesn't help in this case. I create a go snippet with this example: https://play.golang.org/p/IEalgBCsTVR

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
azertiti
  • 3,150
  • 17
  • 19
  • Thanks, I believe if what I'm trying to do is not possible then it's a duplicated as you suggested. I will look into that solution as it seems to accomplish my initial goal, just in a different way. – azertiti Nov 28 '18 at 11:03
  • Possible duplicate of [JSON and dealing with unexported fields](https://stackoverflow.com/questions/11126793/json-and-dealing-with-unexported-fields) – azertiti Dec 03 '18 at 17:35
  • I think my initial approach was incorrect and impossible to work. The correct one is from https://stackoverflow.com/questions/11126793/json-and-dealing-with-unexported-fields I voted to close it as duplicated. – azertiti Dec 03 '18 at 17:36

1 Answers1

0

You need to give json.Unmarshal() a pointer to a concrete type. So change (from your linked playground):

unm := New()

to

unm := New().(value)
poy
  • 10,063
  • 9
  • 49
  • 74
  • That will work as long as we are in the same package. "value" is not exported and my goal is not to allow changes to the map from outside the package. Having an exported interface is best idea I had for this so far but I haven't found a solution to make marshaling/unmarshaling work. – azertiti Nov 27 '18 at 21:14