如何选择性地将JSON编组为结构?

I have a struct:

type Paper struct {
    PID    int    `json:"pID"`
    PTitle string `json:"pTitle"`
    PDesc  string `json:"pDesc"`
    PPwd   string `json:"pPwd"`
}

Mostly, I will encode the entire struct to JSON. However, occasionally, I need the brief version of the struct; i.e. encode some of the properties, how should I implement this feature?

type BriefPaper struct {
    PID    int    `json:"-"`      // not needed
    PTitle string `json:"pTitle"`
    PDesc  string `json:"pDesc"`
    PPwd   string `json:"-"`      // not needed
}

I am thinking of creating a subset struct, something like BriefPaper = SUBSET(Paper), but not sure how to implement it in Golang.

I hope I can do something like this:

p := Paper{ /* ... */ }
pBrief := BriefPaper{}

pBrief = p;
p.MarshalJSON(); // if need full JSON, then marshal Paper
pBrief.MarshalJSON(); // else, only encode some of the required properties

Is it possible?

Probably the easiest way to do this is to create a struct embeds Paper, and shadows the fields you want to hide:

type Paper struct {
    PID    int    `json:"pID"`
    PTitle string `json:"pTitle"`
    PDesc  string `json:"pDesc"`
    PPwd   string `json:"pPwd"`
}

type BriefPaper struct {
    Paper
    PID    int    `json:"pID,omitempty"`  // Just make sure you 
    PPwd   string `json:"pPwd,omitempty"` // don't set these fields!
}

p := Paper{ /* ... */ }
pBrief := BriefPaper{Paper: p}

Now when marshaing BriefPaper, the fields PID and PPwd will be omitted.

Why you just do like this below

type SubPaper struct {
    PID    int    `json:"pID"`
    PPwd   string `json:"pPwd"`
}

type Paper struct {
    SubPaper
    PTitle string `json:"pTitle"`
    PDesc  string `json:"pDesc"`
}

And then marshal the Paper if you want full response

and SubPaper selective things

Using omitempty in tag. Need not specify the items to include while creating the struct instance.

type Paper struct {
    PID    int    `json:"pID,omitempty"`
    PTitle string `json:"pTitle"`
    PDesc  string `json:"pDesc"`
    PPwd   string `json:"pPwd,omitempty"`
}

func main() {
    u := Paper{PTitle: "Title 1", PDesc: "Desc 1"}
    b, _ := json.Marshal(u)

    fmt.Println(string(b))
}

Prints: {"pTitle":"Title 1","pDesc":"Desc 1"}

Only problem is if PID is 0 explicitly then still it will omit it.

Like:

Paper{PTitle: "Title 1", PDesc: "Desc 1", PID:0} Then it will still print {"pTitle":"Title 1","pDesc":"Desc 1"}

Another way to do it using embedded type:

Note that the embedded type has to be pointer so that it can be nil and omitempty can then exclude it.

type Paper struct {
    PID    int    `json:"pID"`    
    PPwd   string `json:"pPwd"`
}

type BriefPaper struct {    
    PTitle string `json:"pTitle"`
    PDesc  string `json:"pDesc"`
    *Paper `json:",omitempty"`  
}

func main() {
    u := BriefPaper{PTitle: "Title 1", PDesc: "Desc 1"}
    b, _ := json.Marshal(u)

    fmt.Println(string(b))
}

Prints: {"pTitle":"Title 1","pDesc":"Desc 1"}

If nested inner struct for paper is required, tag it like *Paper json:"paper,omitempty"