Reputation: 2154
I need to wrap json rpc messages in a go struct This was my first idea and it's working for outgoing messages like this
// Message wrapper
type Message struct {
ID *string `json:"id,omitempty"`
JSONRPC string `json:"jsonrpc"`
Method *string `json:"method,omitempty"`
Params *interface{} `json:"params,omitempty"`
Result *interface{} `json:"result,omitempty"`
}
// NewNotification creates a RPC Notification
func NewNotification(method string, params interface{}) Message {
m := Message{}
m.JSONRPC = "2.0"
m.Method = &method
m.Params = ¶ms
return m
}
type Test struct {
A string `json:"a"`
B string `json:"b"`
}
t := Test{"abc", "def"}
m := NewNotification("testMethod", t)
socket.WriteJSON(m)
But now for the receiving direction I have a problem with the
Params *interface{}
declaration.
I identify the Params
payload type via the Method
field and want to
unmarshal the Params
to that struct ... but therefore I need the type
json.RawMessage
for Params
to get this working.
I do not want to define a MessageIn
and MessageOut
struct!
m := Message{}
socket.ReadJSON(m)
t := Test{}
json.Unmarshal(m.Params, &t)
Upvotes: 0
Views: 385
Reputation: 2154
Ok this idea has a MessageIn
and MessageOut
struct but they share the common part from Message
. This way it's possible to let WriteJson do the marshalling in sending direction. The receiving unmarshal must be done manually when the method and the supposed payload type is known.
// Message wrapper
type Message struct {
ID *string `json:"id,omitempty"`
JSONRPC string `json:"jsonrpc"`
Method *string `json:"method,omitempty"`
}
// MessageIn wrapper
type MessageIn struct {
Message
Params *json.RawMessage `json:"params,omitempty"`
Result *json.RawMessage `json:"result,omitempty"`
}
// MessageOut wrapper
type MessageOut struct {
Message
Params *interface{} `json:"params,omitempty"`
Result *interface{} `json:"result,omitempty"`
}
// NewNotification creates a RPC Notification
func NewNotification(method string, params interface{}) MessageOut {
m := MessageOut{}
m.JSONRPC = "2.0"
m.Method = &method
m.Params = ¶ms
return m
}
type Test struct {
A string `json:"a"`
B string `json:"b"`
}
# let WriteJSON do all marshalling
t := Test{"abc", "def"}
m := NewNotification("testMethod", t)
socket.WriteJSON(m)
# unmarshal manually received message when method is known
m := Message{}
socket.ReadJSON(m)
t := Test{}
json.Unmarshal(m.Params, &t)
Upvotes: 0
Reputation: 366
You should use the json.RawMessage
as the type for your Params and Result Fields. This will delay the decoding of the these fields until you know what is the Method, on the receiving end. Check out the documentation and the examples: it's the same use case: https://golang.org/pkg/encoding/json/#RawMessage
Upvotes: 1