Golang:从URL获取的JSON作为map类型

huangapple go评论72阅读模式
英文:

Golang: Json from URL as map

问题

从URL提取JSON的最佳方法是什么,例如来自Go的REST服务?
此外,似乎大多数Go中的REST客户端库都强制使用json.marshall,它需要与结构体一起使用。

这在不完全了解即将到来的非结构化数据的情况下是行不通的。有没有一种方法可以将所有数据简单地作为map[string:string]传入?

英文:

What is the best way to extract json from a url i.e. Rest service from Go?
Also it seems most rest client libraries in go force a use of the json.marshall which needs a struct to be used with it.

This doesn't work in the case of unstructured data where you don't fully know what will be coming in. Is there a way to have it all simply come in as a map[string:string]?

答案1

得分: 0

为什么不将其解析为map[string]string,因为这段代码需要这样做:

var d map[string]interface{}
data, err := json.Unmarshal(apiResponse, &d)

你也可以在这个结构体中遍历数据。

如果你怀疑API响应可能不是单个对象,而是对象的集合,interface{}也适用于数组。

英文:

Why not to parse it into map[string]string as this code have to do

var d map[string]interface{}
data, err := json.Unmarshal(apiResponse, &d)

You can traverse data in this struct too.

If you suspect, that api response can be not singular object, but the collection of objects, the interface{} also works for arrays.

答案2

得分: 0

如果你不知道消息中会有什么内容,可能会遇到几种情况。

根据类型确定消息内容

通常可以通过某个类型字段来指示类型。在这种情况下,你可以使用一个包含所有类型字段的“联合”结构体:

type Foo struct {
    A int
    B string
}

type Bar struct {
    C int
    D string
}

type Message struct {
    Type string
    Foo
    Bar
}

// 或者,如果有共同的字段

type Message struct {
    Type string
    A int
    B string
    C int
    D string
}

将消息解组为联合结构体,根据类型进行分发,并选择子结构体。

var m Message
json.Unmarshal(data, &m)
switch m.Type {
    case "foo":
        ...
    case "bar":
        ...
}

完全动态的消息

在这种情况下,你有一组不相关的键值对,并且需要逐个处理它们。

解析为map[string]interface{}。当然,缺点是你必须动态地将每个值转换并检查其类型。注意:map[string]interface{}会将所有数字转换为浮点数,即使是整数,所以你需要将它们转换为float64

如果你只想解析键(json.RawMessage[]byte,在解组时保持不变),你也可以使用map[string]json.RawMessage

具有动态载荷的“信封”消息

例如:

{
    "type": "foo",
    "payload": {
        "key1": "value1"
    }
}

{
    "type": "bar",
    "payload": {
        "key2": "value2",
        "key3": [1, 2]
    }
}

使用带有json.RawMessage的结构体。

type Message struct {
    Type string
    Payload json.RawMessage
}

type Foo struct {
    Key1 string
}

type Bar struct {
    Key2 string
    Key3 []int
}

解析信封(载荷将被保留),然后根据类型进行分发,并将载荷解析为子结构体。

var m Message
_ = json.Unmarshal(data, &m)
switch m.Type {
    case "foo":
        var payload Foo
        _ = json.Unmarshal(m.Payload, &payload)
        // 处理操作
    case "bar":
        var payload Bar
        _ = json.Unmarshal(m.Payload, &payload)
        // 处理操作
}
英文:

If you don't know what's coming in a message, you can have several situations.

#Message contents that depend on type

Type is usually indicated by some type field. In this case you can use a "union" struct that contains fields from all types:

type Foo struct {
    A int
    B string
}

type Bar struct {
    C int
    D string
}

type Message struct {
    Type string
    Foo
    Bar
}

// or this, if you have common fields

type Message struct {
    Type string
    A int
    B string
    C int
    D string
}

Unmarshal the message into the union struct, dispatch on type, and select the sub-struct.

var m Message
json.Unmarshal(data, &m)
switch m.Type {
    case "foo":
        ...
    case "bar":
        ...
}

#Completely dynamic messages

In this case you have a collection of unrelated key-values and process them individually.

Parse into a map[string]interface{}. The downside, of course, is that you have to cast each value and check its type dynamically. Caveat: map[string]interface{} will convert all numbers to floats, even integers, so you have cast them to float64.

You can also use map[string]json.RawMessage, if you do not want to parse values, only keys (json.RawMessage is a []byte, and is preserved as is when unmarshaled).

#"Envelope" message with dynamic payload

For example:

{
    "type": "foo",
    "payload": {
        "key1": "value1"
    }
}

{
    "type": "bar",
    "payload": {
        "key2": "value2",
        "key3": [1, 2]
    }
}

Use a struct with json.RawMessage.

type Message struct {
    Type string
    Payload json.RawMessage
}

type Foo struct {
    Key1 string
}

type Bar struct {
    Key2 string
    Key3 []int
}

Parse the envelope (payload will be preserved), then dispatch on type, and parse payload into a sub-struct.

var m Message
_ = json.Unmarshal(data, &m)
switch m.Type {
    case "foo":
        var payload Foo
        _ = json.Unmarshal(m.Payload, &payload)
        // do stuff
    case "bar":
        var payload Bar
        _ = json.Unmarshal(m.Payload, &payload)
        // do stuff
}

huangapple
  • 本文由 发表于 2015年7月5日 21:18:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/31230756.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定