Gedeeltelijk JSON unmarshal in een kaart in Go

Mijn websocket-server zal JSON-gegevens ontvangen en demarshallen. Deze gegevens worden altijd verpakt in een object met sleutel/waarde-paren. De key-string fungeert als waarde-ID en vertelt de Go-server wat voor waarde het is. Door te weten welk type waarde, kan ik vervolgens doorgaan met JSON om de waarde in het juiste type struct te brengen.

Elk json-object kan meerdere sleutel/waarde-paren bevatten.

Voorbeeld JSON:

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

Is er een gemakkelijke manier om het pakket "encoding/json"te gebruiken om dit te doen?

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)
}

Bedankt voor elke vorm van suggestie/hulp!


Antwoord 1, autoriteit 100%

Dit kan worden bereikt door Unmarshaling in een map[string]json.RawMessage.

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

Om sendMsgverder te ontleden, kun je zoiets doen als:

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

Voor saykun je hetzelfde doen en een string uit elkaar halen:

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

BEWERKEN:Houd er rekening mee dat je ook de variabelen in je sendMsg-struct moet exporteren om correct te unmarshallen. Dus je structuurdefinitie zou zijn:

type sendMsg struct {
    User string
    Msg  string
}

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


Antwoord 2, autoriteit 2%

Hier is een elegante manier om iets soortgelijks te doen. Maar waarom unmarshal gedeeltelijk JSON? Dat slaat nergens op.

  1. Maak je structuren voor de Chat.
  2. Decodeer json naar de Struct.
  3. Je hebt nu gemakkelijk toegang tot alles in Struct/Object.

Kijk hieronder naar de werkende code. Kopieer en plak het.

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
   }
 }

Ga naar de speeltuin


Antwoord 3

Verder naar het antwoord van Stephen Weinberg, heb ik sindsdien een handig hulpmiddel geïmplementeerd iojson , die helpt bij Geef gegevens eenvoudig in op een bestaand object en coderen voor het bestaande object naar een JSON-string. Er is ook een iojson-middleware beschikbaar om met andere middlewares te werken. Meer voorbeelden zijn te vinden op Https://github.com/junhsieh/iojson

Voorbeeld:

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())
        }
    }
}

Monsteruitgang:

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

Other episodes