1

I'm following up on Golang Decoding Generic JSON Objects to One of Many Formats as a way to unmarshal generic json. I'm going to have a multitude of different types tho which can be added by others, so hardcoding case statements is not feasible.

I also don't want to hardcode the type as a string, but let the ones using the library chose the "lookup" name, in case they want to rename their underlying structs later.

I am basically looking for something like this:

type myInterface interface {
  Something() // irrelevant, just to show you It's not about interface{}
}

type myBar struct {}       // fulfils myInterface
type mySomething struct {} // fulfils myInterface

var types = make(map[string]type) // <--- Obvious Pseudo code ;)
types["foo:bar"] = myBar       // done by whoever uses the library
types["1230988"] = mySomething // ...

type storageWrapper struct {
  Type string
  Data json.RawMessage
}

func loadSomething(id string) myInterface {
  buf := db.load(id) // pseudo code but you get the idea
  sw := &storageWrapper{}
  json.Unmarshal(buf, sw)

  // now the interesting part
  targetType := types[sw.Type]
  thing := &targetType{}
  json.Unmarshal(sw.Data, thing)
  return thing
}

I have this feeling that I'm overthinking the whole Problem. Or that I'm trying to bend Go into something that conflicts with its underlying philosophy. I'm very open and thankful for any advice that suggests a different approach to the whole Problem

Community
  • 1
  • 1
Pascal
  • 5,879
  • 2
  • 22
  • 34

1 Answers1

0

Have types be a map[string]myInterface, and to register a type, have callers store an empty value of that type (not a reference) into the map. Then, to unmarshal, you can "get the type" by copying the empty value out of the map, unmarshaling into it, and returning it (or a reference to it). The interface value will do the job of identifying which type is wanted. Plus, if users want to default some fields to non-zero/empty values in case they're not provided in the JSON, they can actually do that by storing those values within the struct in the type map.

hobbs
  • 223,387
  • 19
  • 210
  • 288
  • accepting this as the answer because it gets the job done. However, I changed my code by now so it doesn't rely on the types map anymore – Pascal Feb 09 '16 at 00:47