Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Struct switch?

Tags:

struct

go

Let's say I have an application that receives json data in two different formats.

f1 = `{"pointtype":"type1", "data":{"col1":"val1", "col2":"val2"}}`
f2 = `{"pointtype":"type2", "data":{"col3":"val3", "col3":"val3"}}`

And I have a struct associated to each type:

type F1 struct {
  col1 string
  col2 string
}

type F2 struct {
  col3 string
  col4 string
}

Assuming that I use the encoding/json library to turn the raw json data into the struct: type Point { pointtype string data json.RawMessage }

How can I decode the data into the appropiate struct just by knowing the pointtype?

I was trying something along the lines of :

func getType(pointType string) interface{} {
    switch pointType {
    case "f1":
        var p F1
        return &p
    case "f2":
        var p F2
        return &p
    }
    return nil
}

Which is not working because the returned value is an interface, not the proper struct type. How can I make this kind of switch struct selection work?

here is a non working example

like image 544
Manuel G Avatar asked Oct 23 '14 03:10

Manuel G


2 Answers

You can type switch on the interface returned from your method:

switch ps := parsedStruct.(type) {
    case *F1:
        log.Println(ps.Col1)
    case *F2:
        log.Println(ps.Col3)
}

..etc. Remember, for the encoding/json package to decode properly (via reflection), your fields need to be exported (uppercase first letter).

Working sample: http://play.golang.org/p/8Ujc2CjIj8

like image 160
Simon Whitehead Avatar answered Oct 14 '22 19:10

Simon Whitehead


An alternative way would be to use maps (supported by the native json package).

Here I assume that each data attribute (col1, col2 ...) exists, but maps allows you to check it.

package main

import "fmt"
import "encoding/json"

type myData struct {
    Pointtype string
    Data map[string]string
}

func (d *myData) PrintData() {
    if d.Pointtype == "type1" {
        fmt.Printf("type1 with: col1 = %v, col2 = %v\n", d.Data["col1"], d.Data["col2"])
    } else if d.Pointtype == "type2" {
        fmt.Printf("type2 with: col3 = %v, col4 = %v\n", d.Data["col3"], d.Data["col4"])
    } else {
        fmt.Printf("Unknown type: %v\n", d.Pointtype)
    }
}

func main() {
    f1 := `{"pointtype":"type1", "data":{"col1":"val1", "col2":"val2"}}`
    f2 := `{"pointtype":"type2", "data":{"col3":"val3", "col4":"val4"}}`

    var d1 myData
    var d2 myData

    json.Unmarshal([]byte(f1), &d1)
    json.Unmarshal([]byte(f2), &d2)

    d1.PrintData()
    d2.PrintData()
}

http://play.golang.org/p/5haKpG7MXg

like image 30
Sebastien C. Avatar answered Oct 14 '22 18:10

Sebastien C.