Home  >  Article  >  Backend Development  >  How can I reuse a structure from a third-party package while changing the marshalling behavior of individual fields?

How can I reuse a structure from a third-party package while changing the marshalling behavior of individual fields?

PHPz
PHPzforward
2024-02-10 08:18:08973browse

How can I reuse a structure from a third-party package while changing the marshalling behavior of individual fields?

php editor Zimo is here to share a tip on how to reuse structures in third-party packages and change the marshalling behavior of a single field. When we use a third-party package, sometimes we need to customize a field in it. This article will introduce a simple method that can achieve this goal through inheritance and overwriting, which can not only reuse the original structure but also meet personalized needs. Next, let’s take a look at the specific implementation method!

Question content

Suppose I want to marshal a struct into YAML, and the struct has all of its YAML tags defined, except for one that I want to change. How can I change the behavior of this single field without changing the structure itself? Assume that the structure comes from a third party package.

Here is an example to demonstrate, and my best attempt. It is assumed that the User structure (and its associated Secret structure) come from a third-party package, so we cannot modify them.

package main

import (
    "fmt"

    "gopkg.in/yaml.v2"
)

type User struct {
    Email    string  `yaml:"email"`
    Password *Secret `yaml:"password"`
}

type Secret struct {
    s string
}

// MarshalYAML implements the yaml.Marshaler interface for Secret.
func (sec *Secret) MarshalYAML() (interface{}, error) {
    if sec != nil {
        // Replace `"<secret>"` with `sec.s`, and it gets the desired
        // behavior. But I can't change the Secret struct:
        return "<secret>", nil
    }
    return nil, nil
}

func (sec *Secret) UnmarshalYAML(unmarshal func(interface{}) error) error {
    var st string
    if err := unmarshal(&st); err != nil {
        return err
    }
    sec.s = st
    return nil
}

// My best attempt at the solution:
type SolutionAttempt struct {
    User
}

func (sol *SolutionAttempt) MarshalYAML() (interface{}, error) {
    res, err := yaml.Marshal(
        struct {
            // I don't like having to repeat all these fields from User:
            Email    string `yaml:"email"`
            Password string `yaml:"password"`
        }{
            Email:    sol.User.Email,
            Password: sol.User.Password.s,
        },
    )
    if err != nil {
        return nil, err
    }
    return string(res), nil
}

func main() {
    user := &User{}
    var data = `
  email: [email&#160;protected]
  password: asdf
`
    err := yaml.Unmarshal([]byte(data), user)
    if err != nil {
        fmt.Printf("errors! %s", err)
        return
    }

    buf, err := yaml.Marshal(user)
    if err != nil {
        fmt.Printf("errors! %s", err)
        return
    }

    // Without touching User or Secret, how can I unmarshall an
    // instance of User that renders the secret?
    fmt.Printf("marshalled output:\n%s\n", buf)

    ///////////////////////////////////////////////////////
    // attempted solution:
    ///////////////////////////////////////////////////////
    sol := &SolutionAttempt{}
    var data2 = `
user:
    email: [email&#160;protected]
    password: asdf
`
    err = yaml.Unmarshal([]byte(data2), sol)
    if err != nil {
        fmt.Printf("errors! %s", err)
        return
    }

    buf, err = yaml.Marshal(sol)
    if err != nil {
        fmt.Printf("errors! %s", err)
        return
    }
    fmt.Printf("attempted solution marshalled output:\n%s\n", buf)
}

Here is the Go Playground link for the above code: https://go.dev/play/p/ojiPv4ylCEq

Workaround

This is simply not possible.

Your "best attempt" is the right path.

The above is the detailed content of How can I reuse a structure from a third-party package while changing the marshalling behavior of individual fields?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete