代码之家  ›  专栏  ›  技术社区  ›  Aaron N. Brock

将结构编组为json时对字段执行操作

  •  0
  • Aaron N. Brock  · 技术社区  · 6 年前

    我有以下结构:

    type Message struct {
        DoubleMe    int     `json:"double_me"`
        Message     string  `json:"message"`
    }
    

    还有一个例子:

    m := Message{5, "Hello, World!"}
    

    我的目标是给病人做一些手术 DoubleMe 字段,例如将其加倍。因此,输出将是:

    {"double_me":10,"message":"Hello, World!"}
    

    我怎样才能做到这一点?

    1 回复  |  直到 6 年前
        1
  •  3
  •   icza    6 年前

    使生效 json.Marshaler 在您的结构上,定义一个自定义封送逻辑,这可能会使 DoubleMe 领域

    看这个例子:

    type Message struct {
        DoubleMe int    `json:"double_me"`
        Message  string `json:"message"`
    }
    
    func (m Message) MarshalJSON() ([]byte, error) {
        m.DoubleMe *= 2
    
        type Message2 Message
        return json.Marshal(Message2(m))
    }
    
    func main() {
        m := Message{5, "Hello, World!"}
        data, err := json.Marshal(m)
        fmt.Println(string(data), err)
        fmt.Println("Original:", m)
    }
    

    输出(在屏幕上试用) Go Playground ):

    {"double_me":10,"message":"Hello, World!"} <nil>
    Original: {5 Hello, World!}
    

    注意:

    • 如果您也需要反向工作(例如,在解组时,将值除以2),还需要实现 json.Unmarshaler (留给读者作为练习)。

    • 尽管我们将字段翻倍,但在编组后,原始值没有改变。这是因为该方法有一个非指针接收器,所以在该方法中只获取和修改一个副本,而不是原始值。如果我们用的是指针接收器,我们必须修复它。

    • 还要注意的是,一种新的 Message2 MarshalJSON() 方法这是因为我们也使用了 json 一旦我们应用了自定义逻辑,包就可以执行“常规”封送。但如果我们能通过 m json.Marshal() ,这将是一个无休止的“递归”,因为 json 我会再次称之为 MarshallJSON() 方法相反,我们创造了一个 信息2 有类型 Message 作为其基础类型。这意味着 信息2 没有方法(它不实现 json。元帅 ),所以传递一个值 信息2 json。元帅() 不会再次调用此方法,因为它已 消息 作为其基础类型,我们可以简单地转换类型的值 消息 信息2 .