我们希望在生产中将JSON字段value
重命名为v
。直到我们所有的用户都使用新结构,我们将继续将旧的JSON结构添加到我们的代码中。所以我们也希望处理这个问题。
如果您注意到First
是原始结构,Second
是新结构。为了处理这两种结构,我创建了MyStruct
并基于version
,我将OldValue
复制到Value
if m.Version <= 1 {
m.Value = m.OldValue
}
有没有更好的方法来处理这个问题,而不是我的代码。
package main
import "fmt"
import "encoding/json"
import "log"
type First struct {
Version int `json:"version"`
Value int `json:"value"`
}
type Second struct {
Version int `json:"version"`
Value int `json:"v"`
}
type MyStruct struct {
Version int `json:"version"`
OldValue int `json:"value"`
Value int `json:"v"`
}
func main() {
oldValue := []byte(`{"version":1, "value":5}`)
newValue := []byte(`{"version":2, "v":7}`)
var m MyStruct
err := json.Unmarshal(newValue, &m)
if err != nil {
log.Fatal(err)
}
fmt.Println("New Struct")
fmt.Println(m.Value)
err = json.Unmarshal(oldValue, &m)
if err != nil {
log.Fatal(err)
}
fmt.Println("Old Struct")
if m.Version <= 1 {
m.Value = m.OldValue
}
fmt.Println(m.Value)
}
答案 0 :(得分:1)
编辑:您实际上可以通过一次解编来完成,虽然您需要其他类型:
type Second struct {
Version int `json:"version"`
Value int `json:"v"`
}
type SecondWithOldValue struct {
OldValue int `json:"value"`
Second
}
type MyStruct SecondWithOldValue
func (v *MyStruct) UnmarshalJSON(b []byte) error {
if err := json.Unmarshal(b, (*SecondWithOldValue)(v)); err != nil {
return err
}
if v.Version <= 1 {
v.Value = v.OldValue
}
return nil
}
游乐场:https://play.golang.org/p/yII-ncxnU4。
下面的旧答案。
如果您可以通过双重解锁来完成,则可以这样做:
type Second struct {
Version int `json:"version"`
Value int `json:"v"`
}
type MyStruct struct {
Second
}
func (v *MyStruct) UnmarshalJSON(b []byte) error {
if err := json.Unmarshal(b, &v.Second); err != nil {
return err
}
if v.Version <= 1 {
var oldV struct{ Value int }
if err := json.Unmarshal(b, &oldV); err != nil {
return err
}
v.Value = oldV.Value
}
return nil
}
首先,在内部结构中解组,检查版本,如果它是旧版本,请获取旧值。
答案 1 :(得分:0)
我会选择不使用3种不同的结构,因为它们都是相同的。
按原样修改结构MyStruct,并按原样将json:"value"
加载到一个新变量中,如果Value不存在,Unmarshal的一部分应该将值复制到Value变量中。
但是我会在这里推荐Kostix的推荐。您加载和保存数据的API或进程应尝试通过建议的机制考虑版本控制。在您的URI中添加v#,或者如果您将项目保存到磁盘,则可能使用版本号保存它,然后按照与正确版本对应的每个结构处理内部部分:
{
"version": 1,
"struct": { ... }
}