dsfb20227 2015-05-11 17:43 采纳率: 0%
浏览 111
已采纳

在Golang中解码任意JSON

I have a question about decoding arbitrary JSON objects/messages in Go.. Lets say for example you have three wildly different JSON objects (aka messages) that you can receive on an http connection, lets call them for sake of illustration:

{ home : { some unique set of arrays, objects, fields, and arrays objects } }

and

{ bike : { some unique set of arrays, objects, fields, and arrays objects } }

and

{ soda : { some unique set of arrays, objects, fields, and arrays objects } }

What I am thinking is you could decode these, from an http connection in to a map of interfaces such as:

func httpServerHandler(w http.ResponseWriter, r *http.Request) {
    message := make(map[string]interface{})
    decoder := json.NewDecoder(r.Body)
    _ = decoder.Decode(&message)

Then do an if, else if block to look for valid JSON messages

if _, ok := message["home"]; ok {
    // Decode interface{} to appropriate struct
} else if _, ok := message["bike"]; ok {
    // Decode interface{} to appropriate struct
} else {
    // Decode interface{} to appropriate struct
}

Now in the if block I can make it work if I re-decode the entire package, but I was thinking that is kind of a waste since I have already partially decoded it and would only need to decode the value of the map which is an interface{}, but I can not seem to get that to work right.

Redecoding the entire thing works though, if I do something like the following where the homeType for example is a struct:

var homeObject homeType
var bikeObject bikeType
var sodaObject sodaType

Then in the if block do:

if _, ok := message["home"]; ok {
    err = json.Unmarshal(r.Body, &homeObject)
    if err != nil {
        fmt.Println("Bad Response, unable to decode JSON message contents")
        os.Exit(1)
    }

So without re-decoding / unmarshal-ing the entire thing again, how do you work with the interface{} in a map?

  • 写回答

1条回答 默认 最新

  • dongyun7571 2015-05-11 17:45
    关注

    If you have something like a map[string]interface{} then you can access the values using type assertions, e.g.

    home, valid := msg["home"].(string)
    if !valid {
        return
    }
    

    This works nicely for simple values. For more complicated nested structures you might find it easier to do deferred decoding with json.RawMessage or implement a custom json.Unmarshaler. See this for a very detailed discussion.

    Another idea might be to define a custom Message type consisting of pointers to Home, Bike, and Soda structs. Such as

    type Home struct {
        HomeStuff     int
        MoreHomeStuff string
    } 
    
    type Bike struct {
        BikeStuff int
    }
    
    type Message struct {
        Bike *Bike `json:"Bike,omitempty"`
        Home *Home `json:"Home,omitempty"`
    }
    

    If you set these to omit if nil then unmarshalling should only populate the relevant one. You can play with it here.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 C# 调用Bartender打印机打印
  • ¥100 华为ensp只要2-9实验运行结果能做的来加我QQ
  • ¥15 我这个代码哪里有问题 acm 平台上显示错误 90%,我自己运行好像没什么问题
  • ¥50 C#编程中使用printDocument类实现文字排版打印问题
  • ¥15 找会编程的帅哥美女 可以用MATLAB里面的simulink编程,用Keil5编也可以。
  • ¥15 已知隐函数其中一个变量τ的具体值,求另一个变量
  • ¥15 r语言Hurst指数
  • ¥15 Acrn IVSHMEM doorbell问题
  • ¥15 yolov5中的val测试集训练时数量变小问题
  • ¥15 MPLS/VPN实验中MPLS的配置问题