1

我提前为一个长的问题道歉。希望你能忍受我。

我正在使用goweb库,并尝试使用示例网络应用程序

我一直在尝试修改RESTful 示例代码,它将 a 定义Thing为:

type Thing struct {
    Id   string
    Text string
}

AThing是通过向 发送HTTP Post带有适当JSON正文的请求来创建的http://localhost:9090/things。这在Create函数的示例代码中处理,特别是以下行:

dataMap := data.(map[string]interface{})

thing := new(Thing)
thing.Id = dataMap["Id"].(string)
thing.Text = dataMap["Text"].(string)

这一切都很好,我可以运行示例服务器(监听http://localhost:9090/)并且服务器按预期运行。

例如:

curl -X POST -H "Content-Type: application/json" -d '{"Id":"TestId","Text":"TestText"}' http://localhost:9090/things

返回没有错误,然后我GETThing

curl http://localhost:9090/things/TestId

它返回

{"d":{"Id":"TestId","Text":"TestText"},"s":200}

到目前为止,一切都很好。

现在,我想修改Thing类型,并添加一个自定义ThingText类型,如下所示:

type ThingText struct {
    Title   string
    Body    string
}

type Thing struct {
    Id   string
    Text ThingText
}

这本身不是问题,我可以Create像这样修改函数:

thing := new(Thing)
thing.Id = dataMap["Id"].(string)
thing.Text.Title = dataMap["Title"].(string)
thing.Text.Body = dataMap["Body"].(string)

并将上一个curl POST请求JSON设置为:

{"Id":"TestId","Title":"TestTitle","Title":"TestBody"}

它返回没有错误。

GET我再一次可以ThingURL 并返回:

{"d":{"Id":"TestId","Text":{"Title":"TestTitle","Body":"TestBody"}},"s":200}

再说一次,到目前为止,很好。

现在,我的问题:

如何修改Create函数以允许我对其进行POST复杂化JSON

例如,JSON上面最后返回的字符串包括{"Id":"TestId","Text":{"Title":"TestTitle","Body":"TestBody"}}. 我希望能够POST 精确JSON到端点并Thing创建。

我已经按照代码返回,似乎该data变量是Context.RequestData()来自https://github.com/stretchr/goweb/context的类型,而内部Map似乎是Object.Map来自https://github.com/stretchr的类型/stew/,被描述为“具有额外有用功能的地图[字符串]界面{}。” 特别是,我注意到“支持点语法来设置深度值”。

我不知道如何设置thing.Text.Title = dataMap...语句以便将正确的JSON字段解析到其中。string除了中的类型之外,我似乎无法使用其他任何东西dataMap,如果我尝试JSON它会给出类似于以下内容的错误:

 http: panic serving 127.0.0.1:59113: interface conversion: interface is nil, not string

再次为这个荒谬的长问题感到抱歉。我非常感谢您的阅读,以及您可能需要提供的任何帮助。谢谢!

4

1 回答 1

3

正如JSON 包文档JSON 和 Go 介绍所描述的,JSON 数据可以通过 interface{} / 字符串映射进行一般解析,也可以直接解组为结构类型。

您链接到的示例代码并基于您的更改似乎使用通用字符串映射方法,dataMap := data.(map[string]interface{}).

由于您所需的 JSON 数据是对象中的对象,因此它只是地图中的地图。

所以你应该能够

dataMap := data.(map[string]interface{})
subthingMap := dataMap["Text"].(map[string]interface{})
thing.Text.Title = subthingMap["Title"].(string)
thing.Text.Body = subthingMap["Body"].(string)

我不确定为什么该代码使用强制类型转换和泛型类型而不是直接从 JSON 到结构类型的类型安全解组(我猜是抽象)。使用解组到结构类型的 json 包将类似于

type ThingText struct {
    Title   string
    Body    string
}

type Thing struct {
    Id   string
    Text ThingText
}

…
decoder := json.NewDecoder(body)
var thingobj Thing
for {
    if err := decoder.Decode(&thingobj); err == io.EOF {
        break
    } else if err != nil {
        log.Fatal(err)
    }
    fmt.Println(thingobj)
}

哪里bodyio.Reader- 在简单/大多数情况下来自http.Response.Body.

于 2013-06-22T21:08:39.863 回答