检索嵌套 JSON 数组的第一条记录。

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

Retrieve First Record of Nested Json Array

问题

我正在尝试解析嵌套的JSON数组中的第一条记录,并基于其中一部分属性创建一个对象。我已经实现了这个功能,但根据这个问题,我认为可能有一种更优雅/更可靠的方法来实现。更多背景信息,这是从调用musicbrainz JSON Web服务返回的结果集,我将第一个artists记录视为我要查找的艺术家。

JSON的格式如下:

{
    "created": "2014-10-08T23:55:54.343Z",
    "count": 458,
    "offset": 0,
    "artists": [{
        "id": "83b9cbe7-9857-49e2-ab8e-b57b01038103",
        "type": "Group",
        "score": "100",
        "name": "Pearl Jam",
        "sort-name": "Pearl Jam",
        "country": "US",
        "area": {
            "id": "489ce91b-6658-3307-9877-795b68554c98",
            "name": "United States",
            "sort-name": "United States"
        },
        "begin-area": {
            "id": "10adc6b5-63bf-4b4e-993e-ed83b05c22fc",
            "name": "Seattle",
            "sort-name": "Seattle"
        },
        "life-span": {
            "begin": "1990",
            "ended": null
        },
        "aliases": [],
        "tags": []
    },
    ...
}

以下是我目前的代码。我希望能够使用我的ArtistCollection类型来避免一些interface{}的问题,但我不知道如何做。我也不想麻烦地映射艺术家记录的所有属性,我只对"name""id"的值感兴趣。

package main

import (
    "fmt"
    "encoding/json"
    )
    
type Artist struct {
    Id string
    Name string
}

type ArtistCollection struct {
    Artists []Artist
}

func main() {
    raw := //json formatted byte array
    var topLevel interface{}
    err := json.Unmarshal(raw, &topLevel)
    if err != nil {
        fmt.Println("Uh oh")
    } else {
        m := topLevel.(map[string]interface{})
        //this seems really hacky/brittle, there has to be a better way?
        result := (m["artists"].([]interface{})[0]).(map[string]interface{})
        artist := new(Artist)
        artist.Id = result["id"].(string)
        artist.Name = result["name"].(string)
        fmt.Println(artist)
    }
}

请点击这里查看Go Playground中的代码示例:链接

英文:

I'm trying to parse the first record in an embedded JSON array and create an object based on a subset of those properties. I have this working, but based on this question, I have to think there is a more elegant/less brittle way of doing this. For a bit more background, this is a result set from a call to the musicbrainz JSON web service, and I am treating the first artists record as the artist I am looking for.

The format of the JSON is like this:

{
	"created": "2014-10-08T23:55:54.343Z",
	"count": 458,
	"offset": 0,
	"artists": [{
		"id": "83b9cbe7-9857-49e2-ab8e-b57b01038103",
		"type": "Group",
		"score": "100",
		"name": "Pearl Jam",
		"sort-name": "Pearl Jam",
		"country": "US",
		"area": {
			"id": "489ce91b-6658-3307-9877-795b68554c98",
			"name": "United States",
			"sort-name": "United States"
		},
		"begin-area": {
			"id": "10adc6b5-63bf-4b4e-993e-ed83b05c22fc",
			"name": "Seattle",
			"sort-name": "Seattle"
		},
		"life-span": {
			"begin": "1990",
			"ended": null
		},
		"aliases": [],
		"tags": []
	},
    ...
}

Here's the code I have so far. I'd like to be able to use my ArtistCollection type to get around some of the interface{} stuff, but I'm stuck as to how. I also don't want to bother with mapping all of the properties of the artist record, I'm only interested in the "name" and "id" values.

package main

import (
	"fmt"
	"encoding/json"
	)
	
type Artist struct {
	Id string
	Name string
}

type ArtistCollection struct {
	Artists []Artist
}

func main() {
    raw := //json formatted byte array
	var topLevel interface{}
	err := json.Unmarshal(raw, &topLevel)
	if err != nil {
		fmt.Println("Uh oh")
	} else {
		m := topLevel.(map[string]interface{})
		//this seems really hacky/brittle, there has to be a better way?
		result := (m["artists"].([]interface{})[0]).(map[string]interface{})
		artist := new(Artist)
		artist.Id = result["id"].(string)
		artist.Name = result["name"].(string)
		fmt.Println(artist)
	}
}

Requisite go playground link

答案1

得分: 2

定义一个与JSON结构匹配的类型,并将其解组为该类型的值。我在下面使用了一个匿名类型。使用长度为1的数组来获取第一个艺术家记录:

package main

import (
    "encoding/json"
    "fmt"
)

type Artist struct {
    Id   string
    Name string
}

func main() {
    raw := // JSON格式的字节数组
    var result struct {
        Artists []Artist
    }
    err := json.Unmarshal(raw, &result)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("%#v\n", result.Artists[0])
}

playground

英文:

Define a type that matches the structure of the JSON and unmarshal to a value of that type. I use an anonymous type below. Use an array of length one to grab the first artist record:

package main

import (
    "encoding/json"
    "fmt"
)

type Artist struct {
    Id   string
    Name string
}

func main() {
    raw := // JSON formatted byte array
    var result struct {
        Artists artist
    }
    err := json.Unmarshal(raw, &result)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("%#v\n", result.Artists[0])
}

<kbd>playground</kbd>

huangapple
  • 本文由 发表于 2014年10月10日 10:44:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/26291148.html
匿名

发表评论

匿名网友

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

确定