当前位置: 首页 > 面试题库 >

Golang:嵌套JSON Unmarshaler遇到麻烦

卢雅惠
2023-03-14
问题内容

给出以下代码:

package main

import (
    "encoding/json"
    "log"
)

type Somefin string

func (s *Somefin) UnmarshalJSON(b []byte) error {
    log.Println("Unmarshaling",string(b))
    *s = Somefin("~"+string(b)+"~")
    return nil
}

type Wat struct {
    A, B string
    *Somefin
}

func main() {
    b := []byte(`{"A":"foo","B":"bar","Somefin":"baz"}`)
    w := &Wat{Somefin: new(Somefin)}

    err := json.Unmarshal(b,w)
    log.Println(w, err)
}

我得到以下输出:

# go run wat.go
2013/12/14 13:59:17 Unmarshaling {"A":"foo","B":"bar","Somefin":"baz"}
2013/12/14 13:59:17 &{  <nil>} <nil>

因此,Somefin出于某种原因,密钥是试图取消对整个结构的编组,而不是仅仅应该解组。我做错了吗,或者这是json编码器中的错误?顺便说一句,正在进行1.2。


问题答案:

为什么最后没有结果

这不是解码器中的错误,而是代码中的错误。你只是将另一个地址为本地指针sUnmarshalJSON。更正的代码:

func (s *Somefin) UnmarshalJSON(b []byte) error {
    log.Println("Unmarshaling",string(b))
    sn := Somefin("~"+string(b)+"~")
    *s = sn
    return nil
}

语义s = &sn:将地址分配&sns。这类似于s = 42

的语义*s = sn:将所有内容复制sn到指向的地方s

这项工作的一项要求是s指向有效的内存位置,并且不能为nil。您的代码用法示例(播放):

w := &Wat{Somefin: new(Somefin)}

err := json.Unmarshal(b,w)
log.Printf("%#v (%s)\n", w, err)

Crucial是Wat使用new进行的初始化,Somefin因此sin
的指针UnmarshalJSON有效(指向使用创建的对象new(Somefin))。

为什么要输入整个字符串 UnmarshalJSON

嵌入不是多态。虽然嵌入对象(在你的情况的方法集 Somefin)提升到外面,但这 并不 意味着该方法现在工作的嵌入结构,而不是嵌入的一个。

小例子(播放):

type Inner struct { a int }
func (i *Inner) A() int { return i.a }

type Outer struct {
    *Inner
    a int
}

i := &Inner{}
o := Outer{Inner: i}

fmt.Println("Inner.A():", i.A())
fmt.Println("Outer.A():", o.A())

o.a = 2

fmt.Println("Outer.A():", o.A())

有了多态,您将希望Outer.A()返回2因为方法A()将在范围内运行,Outer并且Inner不再运行。嵌入后,作用域A()将永远不会改变,并且
将始终在上运行Inner

相同的效果会阻止您UnmarshalJSON看到这两个成员AB因为它们根本不在以下范围内Somefin

  1. JSON库看到UnmarshalJSONWat,因为UnmarshalJSONSomefin被提升到外
  2. JSON库无法在其中找到任何匹配的元素Somefin并提供整个输入


 类似资料:
  • 问题内容: -edit2-3小时后,仍然有相同的问题。我正在使用noinstall存档软件包。-编辑-也许有人可以告诉我一种检查表是否存在的更好方法? 我的函数库中有一个函数来检查是否存在一个表,该表过去我曾问过要怎么做。 我删除了数据库并再次创建了它。我的代码未正确创建表。调试后,我决定编写以下内容。 很奇怪… mydb被删除并再次创建(我写了,应该消失了吗?)。让我们找出存在的东西 我不仅不知

  • 问题内容: 我的Android应用程序具有登录屏幕,并且用户登录到他的仪表板。但是我不希望用户每次关闭应用程序并启动时都进行登录(除非他们从仪表板上注销)。因此,我创建了一个类来检查用户是否登录 CheckLoggedIn.java 当用户登录时,我将布尔值更改为,并在注销时更改。但是,当我通过成功登录并关闭并再次启动进行检查时,它仍然进入LoginActivity。为什么? 编辑:现在,我明白这

  • 问题内容: 这不是让我输入我的名字,但是年龄确实可以。我知道我可以更改语句的顺序,但是还有另一种方法可以做到吗? 问题答案: 您的问题是,下一个int不考虑输入在您的姓名部分中的换行符。因此,名称返回为空白。 您可以通过两种方式更改代码: 要么 我个人喜欢第二种方式。

  • 我正在使用Service Now Rest API检索服务器上的信息,该信息将作为JSON响应返回,我正在将其解码到python3字典中,这样我就可以进一步提取代码中的特定项,但我很难理解如何使用从JSON创建的嵌套字典。有人能帮我理解如何从字典中提取特定值吗。下面是一个返回的示例(缩短)。 下面是一个响应示例(缩短) 在完成了一些嵌套字典教程之后,我尝试了以下内容,但运气不太好。 TypeErr

  • 问题内容: 它运行。 它也可以运行。 它再次运行! 但是失败了!? Go中的嵌套地图有问题吗?还是对嵌套地图没有多括号支持? 问题答案: 地图类型的零值为。尚未初始化。您无法在地图中存储值,这是运行时的恐慌。 在上一个示例中,您初始化了(外部)映射,但是它没有条目。当您像那样对它进行索引时,由于尚无键输入,因此对其进行索引将返回用于地图的值类型的零值。因此,尝试分配给运行时恐慌。 您必须先初始化地

  • 问题内容: 我正在尝试让CI与Jenkins合作。迄今为止,我们已经在环境中执行了两个计划的构建,但是我们的开发人员希望让CI正常工作。我遵循了Jenkins Subversion插件Wiki页面中概述的说明: https://wiki.jenkins- ci.org/display/JENKINS/Subversion+Plugin 这使我进入了一个可以在命令行执行的脚本,但是当我在Subver