go icon indicating copy to clipboard operation
go copied to clipboard

proposal: encoding/json: add "inline" struct tag

Open gopherbot opened this issue 10 years ago • 39 comments

by bjruth:

Discussion was conceived on golang-nuts:
https://groups.google.com/forum/#!topic/golang-nuts/bAgNll-EMkI to add support for a
flag that supports unmarshaling arbitary JSON into structs. A tag was announced for the
mgo/bson package here:
https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/ZeP7PaXVDQo that
transparently stores data into a separate struct field denoted by "inline"
during an unmarshal and then merges that data back into the output during marshaling.

I believe this would be a very useful feature to add into the encoding/json package and
does not introduce any breaking changes in the Go 1.x series.

Edited by @dsnet on 2020-11-10 to fix formatting.

gopherbot avatar Aug 22 '13 02:08 gopherbot

Comment 1:

I think this is worthwhile. I have an unfinished proposal in my email drafts that is
basically exactly what Gustavo describes in his bson release announcement mail.
It should be simple enough that it could be done before the 1.2 cutoff. Any disagreement?

Labels changed: added priority-soon, go1.2, feature, removed priority-triage.

Owner changed to @adg.

Status changed to Accepted.

adg avatar Aug 22 '13 03:08 adg

Comment 2:

https://golang.org/cl/13180043

Status changed to Started.

adg avatar Aug 28 '13 03:08 adg

Comment 3:

This issue was closed by revision 466001d05d366cbc97edfb65dc6f5cb883df049.

Status changed to Fixed.

adg avatar Aug 29 '13 04:08 adg

Comment 4:

Submitted the CL by mistake.

Status changed to Started.

adg avatar Aug 29 '13 04:08 adg

Comment 5:

This issue was closed by revision 27f4166e372084e1d78119183d14b76391c803c.

Status changed to Fixed.

adg avatar Aug 29 '13 04:08 adg

Comment 6:

And that was the undo CL closing it again :/
New CL https://golang.org/cl/13324045/

Status changed to Started.

adg avatar Aug 29 '13 04:08 adg

Comment 7:

Not going into 1.2.

Labels changed: removed go1.2.

robpike avatar Sep 03 '13 23:09 robpike

Comment 8:

Not even sure this is worthwhile.

Status changed to Thinking.

rsc avatar Sep 05 '13 15:09 rsc

Comment 9 by bjruth:

@rsc It's not that a manual approach doesn't work, but since the unmarshaler already
handles distinguishing known vs. unknown fields relative to the target interface, the
extra data can thrown into a "catch-all" field.

gopherbot avatar Sep 05 '13 16:09 gopherbot

Comment 10:

Labels changed: added go1.3maybe.

rsc avatar Nov 27 '13 18:11 rsc

Comment 11:

Labels changed: removed feature.

rsc avatar Nov 27 '13 20:11 rsc

Comment 12:

Labels changed: added release-none, removed go1.3maybe.

rsc avatar Dec 04 '13 01:12 rsc

Comment 13:

Labels changed: added repo-main.

rsc avatar Dec 04 '13 01:12 rsc

Comment 14:

I really need this. I have a struct that has static and dynamic fields. The dynamic
fields (in a map) are chosen by the user and need to be inline with the static ones.

lukescott avatar Mar 01 '14 00:03 lukescott

Comment 15:

If this is going to be similar to <labix.org/v2/mgo/bson>, ideally an "inline" map
or struct pointer would not be allocated (the field value would remain nil) until there
is something valid to stuff in it.

extemporalgenome avatar Apr 25 '14 17:04 extemporalgenome

Comment 16 by relistan:

+1. I was pondering writing a similar thing and came across this. Essentially we query a
3rd party API that is not versioned and changes. Catching the leftovers would let us
better get a sense of what was skipped. At a minimum it's great for debugging.

gopherbot avatar May 07 '14 03:05 gopherbot

Comment 17 by [email protected]:

+1 I have something where I have a some common fields (id, path, revision, etc) and I
use an anonymous struct that is embedded in other structs. However, I can't implement a
custom json marshal on the common struct as then all the other structs will only return
the output from the marshalled common fields.

gopherbot avatar Jul 11 '14 05:07 gopherbot

Comment 18 by [email protected]:

+1 I have something where I have some common fields (id, path, revision, etc) and I use
an anonymous struct that is embedded in other structs. However, I can't implement a
custom json marshal on the common struct as then all the other structs will only return
the output from the marshalled common fields.

gopherbot avatar Jul 11 '14 05:07 gopherbot

+1

benji-bou avatar Jun 18 '16 14:06 benji-bou

+1 Example use case is retrieving documents stored in MongoDB with a field like this:

Extra    map[string]float32 `bson:",inline"`

to account data that could be missing. This enables reusing same struct defined for inserting also for reading data.

eraclitux avatar Jul 05 '16 17:07 eraclitux

Are there any updates on this?

yefim avatar Mar 28 '17 18:03 yefim

No, and I think the JSON package is pretty frozen for new features.

But I'll promote this to a proposal. This bug predates the proposal process.

bradfitz avatar Mar 28 '17 19:03 bradfitz

Ouch, that is too bad if true.

gitblit avatar Mar 28 '17 19:03 gitblit

After using mgo, I'd love to see ",inline" imported into the standard json library.

JakeWarner avatar Mar 31 '17 00:03 JakeWarner

This feature would allow to catch what is called additionalProperties in JSON Schema.

I don't think however that inline is an appropriate name.

dolmen avatar Apr 15 '17 13:04 dolmen

ping

faguirre1 avatar Jun 09 '17 23:06 faguirre1

Not for Go 1.9. I hope to take a look at all the open json proposals this summer and try to see if a coherent picture emerges.

rsc avatar Jun 14 '17 16:06 rsc

ping. I'd love to see this implemented.

imax9000 avatar Apr 10 '19 12:04 imax9000

I have something where I have a some common fields (id, path, revision, etc) and I use an anonymous struct that is embedded in other structs. However, I can't implement a custom json marshal on the common struct as then all the other structs will only return the output from the marshalled common fields.

Just ran into this.

The use of anonymous structs for inlining is excellent up until your anonymous struct has a MarshalJSON method.

tooolbox avatar Jan 27 '20 20:01 tooolbox

Any update on this from the Go team? @rsc?

smoyer64 avatar Jun 02 '20 11:06 smoyer64

+++++++++++++

mizraelson avatar Oct 08 '20 19:10 mizraelson

Any progress on this, it's waiting for 7 years.

leaxoy avatar Oct 27 '20 08:10 leaxoy

In https://github.com/golang/go/issues/42417 I proposed to have the following syntax:

type Message struct {
  Name  string                 `json:"name"`
  Type  string                 `json:"type"`
  Skip  string                 `json:"-"`
  Extra map[string]interface{} `json:"+"`
}

So + would mark a field into which all extra/unexpected fields would go.

mitar avatar Nov 06 '20 23:11 mitar

+ is an interesting idea, but the + character is already a valid name, so we cannot use that in a backwards compatible way.

dsnet avatar Jan 12 '21 23:01 dsnet

The - character is also a valid name but the encoding/json package lets you use it by adding the json:"-," value. See https://pkg.go.dev/encoding/json#Marshal.

smoyer64 avatar Jan 13 '21 00:01 smoyer64

@smoyer64, that's doesn't fix the issue I mentioned:

  • json:- means this field is ignored
  • json:-, means this field is named "-"

However, today:

  • json:+ means this field is named "+"; and we can't redefine the meaning of this
  • json:+, means this field is named "+"

dsnet avatar Jan 13 '21 00:01 dsnet

encoding/xml supports this via the xml:",any" tag:

  • If the XML element contains a sub-element that hasn't matched any of the above rules and the struct has a field with tag ",any", unmarshal maps the sub-element to that struct field.

(https://golang.org/pkg/encoding/xml/#Unmarshal)

Should the same mechanism be used for encoding/json?

fdcds avatar Apr 22 '21 16:04 fdcds

+1.

Having an element that has a field 'type', and different schema depending on the value of that field is pretty much idiomatic way of building JSON objects / arrays. That's the way most APIs work, and it's surprising that golang, which is the language for servers, does not have strong support for such a common usecase.

bjg2 avatar Apr 25 '22 18:04 bjg2

+1

Comment 18 by [email protected]:

+1 I have something where I have some common fields (id, path, revision, etc) and I use an anonymous struct that is embedded in other structs. However, I can't implement a custom json marshal on the common struct as then all the other structs will only return the output from the marshalled common fields.

parkerroan avatar May 31 '22 21:05 parkerroan

I've read through the comments a few times, and I'm confused.

The ticket is still open, is this still an active proposal? Are we waiting for a better suggestion on syntax / naming?

zelch avatar Aug 29 '22 17:08 zelch

At this point, I'd be happy to have ANY solution - the work-arounds are killers!

smoyer64 avatar Aug 29 '22 18:08 smoyer64