package internal import ( "bytes" "encoding/json" "errors" "fmt" ) type messageOuter struct { Type string } type Message struct { FileOfferMessage *FileOfferMessage FileUnofferMessage *FileUnofferMessage FileTransferRequestMessage *FileTransferRequestMessage SessionInitializedMessage *SessionInitializedMessage } func (m *Message) UnmarshalJSON(b []byte) (err error) { typeObj := new(messageOuter) if err = json.NewDecoder(bytes.NewReader(b)).Decode(typeObj); err != nil { return } switch typeObj.Type { case "fileOffer": v := new(struct { Data *FileOfferMessage }) if err = json.NewDecoder(bytes.NewReader(b)).Decode(v); err != nil { return } m.FileOfferMessage = v.Data case "fileUnoffer": v := new(struct { Data *FileUnofferMessage }) if err = json.NewDecoder(bytes.NewReader(b)).Decode(v); err != nil { return } m.FileUnofferMessage = v.Data case "fileTransferRequest": v := new(struct { Data *FileTransferRequestMessage }) if err = json.NewDecoder(bytes.NewReader(b)).Decode(v); err != nil { return } m.FileTransferRequestMessage = v.Data case "sessionInitialized": v := new(struct { Data *SessionInitializedMessage }) if err = json.NewDecoder(bytes.NewReader(b)).Decode(v); err != nil { return } m.SessionInitializedMessage = v.Data default: err = fmt.Errorf("Invalid message type: %s", typeObj.Type) } return } func (m *Message) MarshalJSON() (b []byte, err error) { var typeName = "" var data interface{} switch { case m.FileOfferMessage != nil: typeName = "fileOffer" data = m.FileOfferMessage case m.FileUnofferMessage != nil: typeName = "fileUnoffer" data = m.FileUnofferMessage case m.FileTransferRequestMessage != nil: typeName = "fileTransferRequest" data = m.FileTransferRequestMessage case m.SessionInitializedMessage != nil: typeName = "sessionInitialized" data = m.SessionInitializedMessage default: err = errors.New("can not encode msg due to unknown message type") return } buf := new(bytes.Buffer) err = json.NewEncoder(buf).Encode(map[string]interface{}{ "type": typeName, "data": data, }) if err != nil { return } b = buf.Bytes() return } type FileOfferMessage struct { FileName string `json:"fileName"` Length uint64 `json:"length"` MimeType string `json:"mimeType"` } type FileTransferRequestMessage struct { FileName string `json:"fileName"` } type FileUnofferMessage struct { FileName string `json:"fileName"` } type SessionInitializedMessage struct { }