Created
February 21, 2022 14:38
-
-
Save ulexxander/43c6d3041321c38923ad0fc45cfdfcb2 to your computer and use it in GitHub Desktop.
Example of using Go json.RawMessage to unmarshal JSON field in struct based on another field determining its expected type.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package twofactorunmarshal | |
import ( | |
"encoding/json" | |
"fmt" | |
"testing" | |
"github.com/pkg/errors" | |
) | |
type Event string | |
const ( | |
EventRegister Event = "register" | |
EventOrder Event = "order" | |
) | |
type RegisterData struct { | |
Username string | |
Password string | |
} | |
type OrderData struct { | |
Currency string | |
Amount float64 | |
} | |
type Message struct { | |
Event Event | |
Data json.RawMessage | |
} | |
func handleMessage(m *Message) error { | |
switch m.Event { | |
case EventRegister: | |
var data RegisterData | |
if err := json.Unmarshal(m.Data, &data); err != nil { | |
return errors.Wrap(err, "unmarshaling FormOnSubmitData") | |
} | |
return handleRegister(&data) | |
case EventOrder: | |
var data OrderData | |
if err := json.Unmarshal(m.Data, &data); err != nil { | |
return errors.Wrap(err, "unmarshaling InputOnChangeData") | |
} | |
return handleOrder(&data) | |
default: | |
return errors.Errorf("unknown event: %s", m.Event) | |
} | |
} | |
func handleRegister(data *RegisterData) error { | |
if data.Username == "" { | |
return errors.New("username cannot be empty") | |
} | |
if len(data.Password) < 6 { | |
return errors.New("password is too short") | |
} | |
fmt.Println("registered user!") | |
return nil | |
} | |
func handleOrder(data *OrderData) error { | |
if data.Currency == "" { | |
return errors.New("currency cannot be empty") | |
} | |
if data.Amount < 0 { | |
return errors.New("amount can not be negative") | |
} | |
fmt.Println("order created successfully!") | |
return nil | |
} | |
func TestUnmarshal(t *testing.T) { | |
t.Run("register", func(t *testing.T) { | |
messageJSON := []byte(`{"event": "register", "data": {"username": "alex", "password": "123456"}}`) | |
var m Message | |
err := json.Unmarshal(messageJSON, &m) | |
if err != nil { | |
t.Fatal(err) | |
} | |
err = handleMessage(&m) | |
if err != nil { | |
t.Fatal(err) | |
} | |
}) | |
t.Run("order invalid data", func(t *testing.T) { | |
messageJSON := []byte(`{"event": "order", "data": [1,2,3]}`) | |
var m Message | |
err := json.Unmarshal(messageJSON, &m) | |
if err != nil { | |
t.Fatal(err) | |
} | |
err = handleMessage(&m) | |
if err == nil { | |
t.Fatal("expected to fail because data is in unexpected structure") | |
} | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment