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 support Unmarshal type interface #23549

Closed
diiyw opened this issue Jan 25, 2018 · 4 comments
Closed

proposal: encoding/json support Unmarshal type interface #23549

diiyw opened this issue Jan 25, 2018 · 4 comments

Comments

@diiyw
Copy link

diiyw commented Jan 25, 2018

package main

import (
	"fmt"
	"encoding/json"
)

type Interface interface {
	Inter()
}

type A struct {
	AValue string
}

func(a *A)Inter() {}

type B struct {
	BValue string
}

func(b *B)Inter() {}


func main() {
	var i Interface
	err := json.Unmarshal([]byte("{\"BValue\":\"B\"}"), &i)
	if err != nil {
		fmt.Println(err)
	}
}

error:json: cannot unmarshal object into Go value of type main.Interface.

A and B implemented Unmarshaler :

package main

import (
	"fmt"
	"encoding/json"
)

type Interface interface {
	Inter()
	UnmarshalJSON([]byte) error
}

type A struct {
	AValue string
}

func(a *A)Inter() {}

func(a *A)UnmarshalJSON([]byte) error{
	return nil
}

type B struct {
	BValue string
}

func(b *B)Inter() {}
func(b *B)UnmarshalJSON([]byte) error{
	return nil
}


func main() {
	var i Interface
	err := json.Unmarshal([]byte("{\"BValue\":\"B\"}"), &i)
	if err != nil {
		fmt.Println(err)
	}
}

The same error,also not ok.
But Marshaler could marshaled.

@gopherbot gopherbot added this to the Proposal milestone Jan 25, 2018
@mvdan
Copy link
Member

mvdan commented Jan 25, 2018

There is nothing that encoding/json can do here. It can unmarshal into a map[string]interface{}, but then that type isn't named and cannot have any methods, thus it cannot satisfy a non-empty interface.

And encoding/json cannot magically know that it could use types A or B. And, even if it did know, which one would it choose?

So really, you should either unmarshal into map[string]interface{}, or one of your two named struct types.

@mattn
Copy link
Member

mattn commented Jan 25, 2018

If use json.RawMessage, and you write switc/case for AValue/BValue.

package main

import (
	"encoding/json"
	"fmt"
)

type Interface interface {
	Inter()
}

type A struct {
	AValue string
}

func (a *A) Inter() {
}

type B struct {
	BValue string
}

func (b *B) Inter() {
}

type Something struct {
	Value interface{}
}

func (s *Something) UnmarshalJSON(b []byte) error {
	var r map[string]*json.RawMessage
	err := json.Unmarshal(b, &r)
	if err != nil {
		return err
	}
	for k, v := range r {
		switch k {
		case "AValue":
			var a A
			if err = json.Unmarshal([]byte(*v), &a.AValue); err != nil {
				return err
			}
			s.Value = a
		case "BValue":
			var b B
			if err = json.Unmarshal([]byte(*v), &b.BValue); err != nil {
				return err
			}
			s.Value = b
		}
	}
	return nil
}

func main() {
	var i Something
	err := json.Unmarshal([]byte("{\"BValue\":\"B\"}"), &i)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(i.Value.(B).BValue)
}

@rsc
Copy link
Contributor

rsc commented Jan 29, 2018

As @mvdan said, there's nothing that can be done here. You can't unmarshal into a nil interface - what methods should be used?

@rsc rsc closed this as completed Jan 29, 2018
@gopherbot
Copy link

Change https://golang.org/cl/107196 mentions this issue: net: enable TCP keepalives by default

CAFxX added a commit to CAFxX/go that referenced this issue Oct 19, 2018
This is just the first step in attempting to make all network connection have
timeouts as a "safe default". TCP keepalives only protect against certain
classes of network and host issues (e.g. server/OS crash), but do nothing
against application-level issues (e.g. an application that accepts connections
but then fails to serve requests).

The actual keep-alive duration (15s) is chosen to cause broken connections
to be closed after 2~3 minutes (depending on the OS, see golang#23549 for details).
We don't make the actual default value part of the public API for a number of
reasons:
- because it's not very useful by itself: as discussed in golang#23549 the actual
  "timeout" after which the connection is torn down is duration*(KEEPCNT+1),
  and we use the OS-wide value for KEEPCNT because there's currently no way
  to set it from Go.
- because it may change in the future: if users need to rely on a specific
  value they should explicitly set this value instead of relying on the default.

Fixes golang#23459

Change-Id: I348c03be97588d5001e6de0f377e7a93b51957fd
gopherbot pushed a commit that referenced this issue Dec 3, 2018
This is just the first step in attempting to make all network connection have
timeouts as a "safe default". TCP keepalives only protect against certain
classes of network and host issues (e.g. server/OS crash), but do nothing
against application-level issues (e.g. an application that accepts connections
but then fails to serve requests).

The actual keep-alive duration (15s) is chosen to cause broken connections
to be closed after 2~3 minutes (depending on the OS, see #23549 for details).
We don't make the actual default value part of the public API for a number of
reasons:
- because it's not very useful by itself: as discussed in #23549 the actual
  "timeout" after which the connection is torn down is duration*(KEEPCNT+1),
  and we use the OS-wide value for KEEPCNT because there's currently no way
  to set it from Go.
- because it may change in the future: if users need to rely on a specific
  value they should explicitly set this value instead of relying on the default.

Fixes #23459

Change-Id: I348c03be97588d5001e6de0f377e7a93b51957fd
Reviewed-on: https://go-review.googlesource.com/c/107196
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
@golang golang locked and limited conversation to collaborators Apr 15, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants