Decoding incoming JSON in Golang based on parameter values

I am trying to decode incoming JSON in my REST API written in Go. I am using a function decoder.Decode()

and my problem is that I need to apply certain rules according to which structure should be used in the decoding process, because sometimes JSON contains:

"type": {
    "type" : "string",
    "maxLength" : 30
},

      

and sometimes:

"type": {
    "type" : "integer",
    "max" : 30,
    "min" : 10
},

      

I somehow need to tell Go that "If type.type is a string, use this struct ( type Type_String struct

), and if type.type is an integer, use another struct ( type Type_Integer struct

)". I'm not sure how to do this. One solution I think is to create a generic structure with all possible properties, use it on any object and then filter properties based on the property type

, but this is so messy. I guess I can write my own decoder too, but this is a bit strange too.

I'm new to Go and I'm pretty much accustomed to the free JavaScript sentences.

+3


source to share


2 answers


You can always decode interface {} as mentioned here: How to access interface fields in json decode?

http://play.golang.org/p/3z8-unhsH4

package main

import (
    "encoding/json"
    "fmt"
)

var one string = `{"type": {"type": "string", "maxLength":30}}`
var two string = `{"type": {"type": "integer", "max":30, "min":10}}`

func f(data map[string]interface{}) {
    t := data["type"]
    typemap := t.(map[string]interface{})
    t2 := typemap["type"].(string)
    switch t2 {
    case "string":
        fmt.Println("maxlength:", typemap["maxLength"].(float64))
    case "integer":

        fmt.Println("max:", typemap["max"].(float64))
    default:
        panic("oh no!")
    }
}

func main() {
    var jsonR map[string]interface{}
    err := json.Unmarshal([]byte(one), &jsonR)
    if err != nil {
        panic(err)
    }
    f(jsonR)
    json.Unmarshal([]byte(two), &jsonR)
    f(jsonR)
}

      



The idea is to decouple the [string] interface {} map and then cast and compare before accessing the values.

In the above code, the function f is casting and comparing. Given this bad json, I used the wrong t and t2 variable name to represent json values โ€‹โ€‹of type "at different depths". Once t2 has a value, the switch statement does something with "string" or "integer" and what it does is print the maximum length or maximum value.

0


source


First of all, if the "type" fields depend on the type.type, in my opinion it is better to move it one level up. Something like:

...
"type" : "integer",
"intOptions": {
    "max" : 30,
    "min" : 10
},
....

      

Then you can create a structure with just one field:

type Type struct {
    Type string
}

      



and do something like:

myType := new(Type)
json.Unmarshal([]byte(yourJsonString), myType)

      

And now, depending on the value of myType, you can use different structures to decode your json.

+1


source







All Articles