简体   繁体   English

部分 JSON 解组为 Go 中的地图

[英]Partly JSON unmarshal into a map in Go

My websocket server will receive and unmarshal JSON data.我的 websocket 服务器将接收和解组 JSON 数据。 This data will always be wrapped in an object with key/value pairs.此数据将始终包装在具有键/值对的对象中。 The key-string will act as value identifier, telling the Go server what kind of value it is. key-string 将充当值标识符,告诉 Go 服务器它是什么类型的值。 By knowing what type of value, I can then proceed to JSON unmarshal the value into the correct type of struct.通过了解值的类型,我可以继续 JSON 将值解组为正确的结构类型。

Each json-object might contain multiple key/value pairs.每个 json 对象可能包含多个键/值对。

Example JSON:示例 JSON:

{
    "sendMsg":{"user":"ANisus","msg":"Trying to send a message"},
    "say":"Hello"
}

Is there any easy way using the "encoding/json" package to do this?有没有使用"encoding/json"包的简单方法来做到这一点?

package main

import (
    "encoding/json"
    "fmt"
)

// the struct for the value of a "sendMsg"-command
type sendMsg struct {
    user string
    msg  string
}
// The type for the value of a "say"-command
type say string

func main(){
    data := []byte(`{"sendMsg":{"user":"ANisus","msg":"Trying to send a message"},"say":"Hello"}`)

    // This won't work because json.MapObject([]byte) doesn't exist
    objmap, err := json.MapObject(data)

    // This is what I wish the objmap to contain
    //var objmap = map[string][]byte {
    //  "sendMsg": []byte(`{"user":"ANisus","msg":"Trying to send a message"}`),
    //  "say": []byte(`"hello"`),
    //}
    fmt.Printf("%v", objmap)
}

Thanks for any kind of suggestion/help!感谢您提供任何建议/帮助!

This can be accomplished by Unmarshaling into a map[string]json.RawMessage .这可以通过解组为map[string]json.RawMessage来完成。

var objmap map[string]json.RawMessage
err := json.Unmarshal(data, &objmap)

To further parse sendMsg , you could then do something like:要进一步解析sendMsg ,您可以执行以下操作:

var s sendMsg
err = json.Unmarshal(objmap["sendMsg"], &s)

For say , you can do the same thing and unmarshal into a string:对于say ,您可以做同样的事情并将其解组为一个字符串:

var str string
err = json.Unmarshal(objmap["say"], &str)

EDIT: Keep in mind you will also need to export the variables in your sendMsg struct to unmarshal correctly.编辑:请记住,您还需要导出 sendMsg 结构中的变量才能正确解组。 So your struct definition would be:所以你的结构定义是:

type sendMsg struct {
    User string
    Msg  string
}

Example: https://play.golang.org/p/OrIjvqIsi4-示例:https: //play.golang.org/p/OrIjvqIsi4-

Here is an elegant way to do similar thing.这是做类似事情的优雅方式。 But why do partly JSON unmarshal?但为什么部分 JSON 解组? That doesn't make sense.那没有意义。

  1. Create your structs for the Chat.为聊天创建结构。
  2. Decode json to the Struct.将 json 解码为结构。
  3. Now you can access everything in Struct/Object easily.现在您可以轻松访问 Struct/Object 中的所有内容。

Look below at the working code.请看下面的工作代码。 Copy and paste it.复制并粘贴它。

import (
   "bytes"
   "encoding/json" // Encoding and Decoding Package
   "fmt"
 )

var messeging = `{
"say":"Hello",
"sendMsg":{
    "user":"ANisus",
    "msg":"Trying to send a message"
   }
}`

type SendMsg struct {
   User string `json:"user"`
   Msg  string `json:"msg"`
}

 type Chat struct {
   Say     string   `json:"say"`
   SendMsg *SendMsg `json:"sendMsg"`
}

func main() {
  /** Clean way to solve Json Decoding in Go */
  /** Excellent solution */

   var chat Chat
   r := bytes.NewReader([]byte(messeging))
   chatErr := json.NewDecoder(r).Decode(&chat)
   errHandler(chatErr)
   fmt.Println(chat.Say)
   fmt.Println(chat.SendMsg.User)
   fmt.Println(chat.SendMsg.Msg)

}

 func errHandler(err error) {
   if err != nil {
     fmt.Println(err)
     return
   }
 }

Go playground去游乐场

Further to Stephen Weinberg's answer, I have since implemented a handy tool called iojson , which helps to populate data to an existing object easily as well as encoding the existing object to a JSON string.除了 Stephen Weinberg 的回答之外,我还实现了一个名为iojson的便捷工具,它有助于轻松地将数据填充到现有对象并将现有对象编码为 JSON 字符串。 A iojson middleware is also provided to work with other middlewares.还提供了一个 iojson 中间件来与其他中间件一起工作。 More examples can be found at https://github.com/junhsieh/iojson更多示例可以在https://github.com/junhsieh/iojson找到

Example:例子:

func main() {
    jsonStr := `{"Status":true,"ErrArr":[],"ObjArr":[{"Name":"My luxury car","ItemArr":[{"Name":"Bag"},{"Name":"Pen"}]}],"ObjMap":{}}`

    car := NewCar()

    i := iojson.NewIOJSON()

    if err := i.Decode(strings.NewReader(jsonStr)); err != nil {
        fmt.Printf("err: %s\n", err.Error())
    }

    // populating data to a live car object.
    if v, err := i.GetObjFromArr(0, car); err != nil {
        fmt.Printf("err: %s\n", err.Error())
    } else {
        fmt.Printf("car (original): %s\n", car.GetName())
        fmt.Printf("car (returned): %s\n", v.(*Car).GetName())

        for k, item := range car.ItemArr {
            fmt.Printf("ItemArr[%d] of car (original): %s\n", k, item.GetName())
        }

        for k, item := range v.(*Car).ItemArr {
            fmt.Printf("ItemArr[%d] of car (returned): %s\n", k, item.GetName())
        }
    }
}

Sample output:示例输出:

car (original): My luxury car
car (returned): My luxury car
ItemArr[0] of car (original): Bag
ItemArr[1] of car (original): Pen
ItemArr[0] of car (returned): Bag
ItemArr[1] of car (returned): Pen

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM