Last active
August 28, 2018 20:06
-
-
Save narqo/af6d83b0ccf66e8e643aa89cb8625753 to your computer and use it in GitHub Desktop.
Rename struct's fields while keep supporting old JSON data
This file contains 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 callback_test | |
import ( | |
"encoding/json" | |
"fmt" | |
"reflect" | |
"testing" | |
"time" | |
) | |
type Data struct { | |
// renamed from ClickTime | |
EngagementTime time.Time `json:"engagement_time,omitempty"` | |
// Deprecated: legacy field we want to switch from gracefully; use EngagementTime | |
ClickTime time.Time `json:",omitempty"` | |
} | |
func (data *Data) UnmarshalJSON(b []byte) error { | |
// new type to prevent recursive Data.UnmarshalJSON calls | |
type NoMethodsData Data | |
var legacyData NoMethodsData | |
if err := json.Unmarshal(b, &legacyData); err != nil { | |
return err | |
} | |
*data = Data(legacyData) | |
if data.EngagementTime.IsZero() { | |
// no new field was set, fallback to legacy field | |
data.EngagementTime = legacyData.ClickTime | |
} | |
return nil | |
} | |
func TestData_legacyFields(t *testing.T) { | |
t1 := time.Now().Truncate(time.Second) | |
v1, _ := t1.MarshalText() | |
cases := []struct { | |
json string | |
data Data | |
}{ | |
{ | |
fmt.Sprintf(`{"engagement_time": "%s"}`, v1), | |
Data{ | |
EngagementTime: t1, | |
ClickTime: time.Time{}, | |
}, | |
}, | |
{ | |
fmt.Sprintf(`{"ClickTime": "%s"}`, v1), | |
Data{ | |
EngagementTime: t1, | |
ClickTime: t1, | |
}, | |
}, | |
} | |
for n, tc := range cases { | |
var data Data | |
if err := json.Unmarshal([]byte(tc.json), &data); err != nil { | |
t.Fatal(err) | |
} | |
if !reflect.DeepEqual(tc.data, data) { | |
t.Errorf("case %d: want %+v, got %+v", n, tc.data, data) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment