我有一个 JSON 对象,其中包含一个接口(interface)的实现。我正在尝试采用该 JSON 并将其编码到一个结构中,同时创建接口(interface)的实现。
我已经设法让它通过自定义 JSON 解码函数实现接口(interface),但是我正在努力拼凑如何然后编码其余字段
我在 Go playground 中创建了一个示例
https://play.golang.org/p/ztF7H7etdjM
传递到我的应用程序中的 JSON 是
{
"address":"1FYuJ4MsVmpzPoFJ6svJMJfygn91Eubid9",
"nonce":13,
"network_id":"qadre.demo.balance",
"challenge":"f2b19e71876c087e681fc092ea3a34d5680bbfe772e40883563e1d5513bb593f",
"type":"verifying_key",
"verifying_key":{
"verifying_key":"3b6a27bcceb6a42d62a3a8d02a6f0d73653215771de243a63ac048a18b59da29",
"fqdn":"huski.service.key"
},
"signature":"a3bf8ee202a508d5a5632f50b140b70b7095d8836493dc7ac4159f6f3350280078b3a58b2162a240bc8c7485894554976a9c7b5d279d3f5bf49fec950f024e02",
"fqdn":"huski.service.SingleKeyProof"
}
我尝试执行 json.Unmarshal 并为剩余字段传入一个新结构,但它似乎使我陷入无限循环,我的应用程序挂起然后崩溃
到目前为止我想出的最好的解决方案是将 JSON 编码到一个 `map[string]interface{} 中并分别处理每个字段,虽然这感觉很笨重
var m map[string]interface{}
if err := json.Unmarshal(data, &m); err != nil {
return err
}
ad, ok := m["address"]
if ok {
s.Address = ad.(string)
}
fqdn, ok := m["fqdn"]
if ok {
s.FQDN = fqdn.(string)
}
n, ok := m["nonce"]
if ok {
s.Nonce = int64(n.(float64))
}
c, ok := m["challenge"]
if ok {
s.Challenge = []byte(c.(string))
}
network, ok := m["network_id"]
if ok {
s.NetworkID = network.(string)
}
sig, ok := m["signature"]
if ok {
s.Signature = []byte(sig.(string))
}
最佳答案
当您尝试解码其余字段时,您的代码进入无限循环的原因是,我推测,UnmarshalJSON
的实现在完成解码验证 key 后调用 json.Unmarshal
与接收方一起调用,后者又调用接收方的 UnmarshalJSON
方法,因此它们会无限期地相互调用。
你可以做的是使用现有类型作为其定义来创建一个临时类型,这将“保留结构”但“删除方法”,然后将其余字段解码为新类型的实例,并且,在解码完成后,将实例转换为原始类型并将其分配给接收者。
虽然这修复了无限循环,但它也重新引入了 json.Unmarshal
无法解码为非空接口(interface)类型的原始问题。要解决这个问题,您可以将新类型嵌入到另一个临时结构中,该结构具有与有问题的字段具有相同 json 标记的字段,这将导致它在 json.Unmarshal
工作时被“掩盖” .
type SingleKey struct {
FQDN string `json:"fqdn"`
Address string `json:"address"`
Nonce int64 `json:"nonce"`
Challenge []byte `json:"challenge"`
NetworkID string `json:"network_id"`
Type string `json:"type"`
VerifyingKey PublicKey `json:"verifying_key"`
Signature []byte `json:"signature"`
}
func (s *SingleKey) UnmarshalJSON(data []byte) error {
type _SingleKey SingleKey
var temp struct {
RawKey json.RawMessage `json:"verifying_key"`
_SingleKey
}
if err := json.Unmarshal(data, &temp); err != nil {
return err
}
*s = SingleKey(temp._SingleKey)
switch s.Type {
case "verifying_key":
s.VerifyingKey = &PublicKeyImpl{}
// other cases ...
}
return json.Unmarshal([]byte(temp.RawKey), s.VerifyingKey)
}
关于json - 执行自定义解码后解码剩余的 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62951510/