2017-08-26 8 views
0

QUESTIONgolang | des données arbitraires unmarshalling

est-il un moyen de données JSON marshall de telle manière qu'il puisse être unmarshalled dans les parties/sections? Disons que la moitié supérieure des données est un "code" qui indiquerait quoi faire avec la moitié inférieure ... comme unmarshall la moitié inférieure dans une structure spécifique en fonction du "code".


Il y a deux struct qui peuvent être envoyés comme la moitié inférieure ...

type Range Struct { 
    Start int 
    End int 

} 

type User struct { 
    ID int 
    Pass int 
} 

PSEUDO CODE EXEMPLE

Il peut ressembler à ceci ...

message := &Message{ 
    Code: 4, 
    &Range { 
     Start: 1, 
     End: 10, 
    } 
} 

Cela peut ressembler à ça ...

message := &Message{ 
    Code: 3, 
    &User { 
     ID: 1, 
     Pass: 1234, 
    } 
} 

Ainsi, lorsque unmarshalling que les données que je pouvais ...

// get code from top half 
m := Message{} 
err = json.UnMarshallTopHalf(byteArray, &m) 
if m.Code == 4 { 
    // ok, the code was four, lets unmarshall into type Range 
    r := Range{} 
    json.UnmarshalBottomHalf(byteArray, &r) 
} 

J'ai regardé JSON & Go apprendre à Marshall et struct définis unmarshall. Je peux le faire, mais je ne peux pas trouver un moyen pour les données arbitraires comme dans l'exemple ci-dessus ...

+1

La bonne option peut être d'utiliser des interfaces, voir http://gregtrowbridge.com/golang-json-serialization-with-interfaces/- n'ont pas essayé ce code, mais cette approche semble correcte. – Ravi

+0

@Ravi | Je crois que c'est l'approche que je vais devoir adopter. Si vous le mettez dans une forme de réponse, je l'accepterai. –

Répondre

1

Vous pouvez unmarshall moitié inférieure en json.RawMessage d'abord, quelque chose comme

package main 

import (
    "encoding/json" 
    "fmt" 
) 

type Message struct { 
    Code int 
    Payload json.RawMessage // delay parsing until we know the code 
} 
type Range struct { 
    Start int 
    End int 
} 
type User struct { 
    ID int 
    Pass int 
} 

func MyUnmarshall(m []byte) { 
    var message Message 
    var payload interface{} 
    json.Unmarshal(m, &message) // delay parsing until we know the color space 
    switch message.Code { 
    case 3: 
     payload = new(User) 
    case 4: 
     payload = new(Range) 
    } 
    json.Unmarshal(message.Payload, payload) //err check ommited for readability 
    fmt.Printf("\n%v%+v", message.Code, payload) //do something with data 
} 

func main() { 
    json := []byte(`{"Code": 4, "Payload": {"Start": 1, "End": 10}}`) 
    MyUnmarshall(json) 
    json = []byte(`{"Code": 3, "Payload": {"ID": 1, "Pass": 1234}}`) 
    MyUnmarshall(json) 
} 
+0

C'est exactement ce que je cherche –

1
type Message struct { 
    Code int `json:"cc"` 
    Range *Range `json:"vvv,omitempty"` 
    User *User `json:"fff,omitempty"` 
} 

puis le code donné == x, plage d'utilisation, si Y, utilisez Utilisateur.

+0

Bien que cette approche soit vraiment pratique, la portée du projet réel est beaucoup plus grande que l'exemple donné. –