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

PHPz
Release: 2024-02-10 08:18:08
forward
980 people have browsed it

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)
}
Copy after login

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!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!