Partly JSON unmarshal into a map in Go

前端 未结 3 1817
一向
一向 2020-11-29 15:34

My websocket server will receive and unmarshal JSON data. This data will always be wrapped in an object with key/value pairs. The key-string will act as value identifier, te

相关标签:
3条回答
  • 2020-11-29 16:15

    This can be accomplished by Unmarshaling into a 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:

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

    For say, you can do the same thing and unmarshal into a string:

    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. So your struct definition would be:

    type sendMsg struct {
        User string
        Msg  string
    }
    

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

    0 讨论(0)
  • 2020-11-29 16:32

    Here is an elegant way to do similar thing. But why do partly JSON unmarshal? That doesn't make sense.

    1. Create your structs for the Chat.
    2. Decode json to the Struct.
    3. Now you can access everything in Struct/Object easily.

    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

    0 讨论(0)
  • 2020-11-29 16:36

    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. A iojson middleware is also provided to work with other middlewares. More examples can be found at 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
    
    0 讨论(0)
提交回复
热议问题