Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: encoding/json: add "Skip when Unmarshalling" tag #19423

Closed
aktungmak opened this issue Mar 6, 2017 · 2 comments

Comments

Projects
None yet
4 participants
@aktungmak
Copy link

commented Mar 6, 2017

I propose adding a new struct tag to the json/encoding package that tells the unmarshaller to skip a field when it is unmarshalling, and leave the existing value as-is.
This mirrors the behaviour the "-" option in the marshal operation.

An example use case of this is a RESTful API service that serves JSON data, and also accepts JSON data from clients to update the data. The endpoint is represented as a struct:

type Endpoint struct {
	VariableField string `json:"variable"`
	FixedField    string `json:"fixed"`
}

func NewEndpoint() *Endpoint {
	var ep *Endpoint
	ep.FixedField = "/should/never/change"
	return ep
}

In this case the client might want to GET the endpoint, modify the data and then POST it directly back. However, if we unmarshal this directly into an Endpoint struct, the client could accidentally (or purposefully) overwrite our fixed field. ´To fix this, lets add a semantic to the struct tag to express that this field should be skipped by the unmarshaller:

type Endpoint struct {
	VariableField string `json:"variable,skip"`
	FixedField    string `json:"fixed"`
}

I used the term "skip" here as an example, perhaps we can use some clearer terminology in the actual implementation.

In this trivial example it is simple to add some logic that ignores this field in the request handler. However, in larger structs it becomes clearer and less error-prone to have a declarative way to express that a value should not be modified by the unmarshalling process.

@rsc rsc changed the title Proposal: Add "Skip when Unmarshalling" tag to encoding/json.Unmarshal Proposal: encoding/json: add "Skip when Unmarshalling" tag Mar 6, 2017

@rsc rsc changed the title Proposal: encoding/json: add "Skip when Unmarshalling" tag proposal: encoding/json: add "Skip when Unmarshalling" tag Mar 6, 2017

@bradfitz bradfitz added this to the Proposal milestone Mar 6, 2017

@bradfitz bradfitz added the Proposal label Mar 6, 2017

@rsc

This comment has been minimized.

Copy link
Contributor

commented Mar 7, 2017

The "-" option already applies to both Marshal and Unmarshal. This new behavior is more like a one-way mirror.

I don't think this pulls its weight as far as adding to the standard library: ignoring a field completely is common, but only wanting to include it in half the operations much less so, and it's already possible to get this behavior by defining your own type for the fixed field:

package main

import (
	"encoding/json"
	"fmt"
)

type Animal struct {
	Name  ReadOnlyString
	Order string
}

type ReadOnlyString string

func (ReadOnlyString) UnmarshalJSON([]byte) error { return nil }

func main() {
	x := Animal{"Bob", "First"}
	js, err := json.Marshal(&x)
	if err != nil {
		fmt.Println("error:", err)
	}
	fmt.Printf("%s\n", js)

	var jsonBlob = []byte(`{"Name": "Platypus", "Order": "Monotremata"}`)
	if err := json.Unmarshal(jsonBlob, &x); err != nil {
		fmt.Println("error:", err)
	}
	fmt.Printf("%#v\n\n", x)
}

https://play.golang.org/p/-mwBL0kIqM

@rsc rsc closed this Mar 7, 2017

@aktungmak

This comment has been minimized.

Copy link
Author

commented Mar 9, 2017

OK, thank you for the feedback and the code example - that answers my use case perfectly!

@golang golang locked and limited conversation to collaborators Mar 9, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.