重命名为JSON字段

时间:2015-10-20 11:57:25

标签: json go

我们希望在生产中将JSON字段value重命名为v。直到我们所有的用户都使用新结构,我们将继续将旧的JSON结构添加到我们的代码中。所以我们也希望处理这个问题。

如果您注意到First是原始结构,Second是新结构。为了处理这两种结构,我创建了MyStruct并基于version,我将OldValue复制到Value

if m.Version <= 1 {
    m.Value = m.OldValue
}

有没有更好的方法来处理这个问题,而不是我的代码。

Go Playground Link

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)

}

2 个答案:

答案 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
}

首先,在内部结构中解组,检查版本,如果它是旧版本,请获取旧值。

游乐场:https://play.golang.org/p/AaULW6vJz_

答案 1 :(得分:0)

我会选择不使用3种不同的结构,因为它们都是相同的。

按原样修改结构MyStruct,并按原样将json:"value"加载到一个新变量中,如果Value不存在,Unmarshal的一部分应该将值复制到Value变量中。

但是我会在这里推荐Kostix的推荐。您加载和保存数据的API或进程应尝试通过建议的机制考虑版本控制。在您的URI中添加v#,或者如果您将项目保存到磁盘,则可能使用版本号保存它,然后按照与正确版本对应的每个结构处理内部部分:

{
    "version": 1,
    "struct": { ... }
}