根据参数值解码Golang中的传入JSON

时间:2014-12-25 00:32:14

标签: json struct go

我正在尝试在Go中编写的REST API中解码传入的JSON。我正在使用decoder.Decode()函数,我的问题是我需要对解码过程中应该使用哪个结构应用某些规则,因为有时JSON包含:

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

有时候:

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

我不知何故需要告诉Go“如果type.type是字符串,请使用此结构(type Type_String struct),如果type.type是整数,请使用其他结构(type Type_Integer struct)”。我不确定该怎么做。我想到的一个解决方案是创建一个具有所有可能属性的通用结构,在任何类型的对象上使用它,然后根据type属性过滤属性,但这很脏。我想我也可以编写自己的解码器,但这看起来也有点奇怪。

我是Go的新手,我非常习惯JavaScript提供的自由。

2 个答案:

答案 0 :(得分:1)

首先,如果“type”的字段取决于“type.type”,在我看来,最好将其移动一级。类似的东西:

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

然后你可以创建一个只有一个字段的结构:

type Type struct {
    Type string
}

并执行以下操作:

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

现在,根据myType的值,您可以使用不同的结构来解码您的json。

答案 1 :(得分:0)

您可以随时解码到此处提到的界面{}:How to access interface fields on 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)
}

我们的想法是解组map [string] interface {},然后在访问值之前进行转换和比较。

在上面的代码中,f函数执行强制转换和比较。鉴于这个可怜的json,我使用了差的变量名t和t2来表示"类型"的json值。在不同的深度。一旦t2具有该值,switch语句就会使用" string"或者"整数"它的作用是打印maxLength或最大值。