登录
首页 >  Golang >  Go问答

Golang中根据对象值对JSON解析进行排序

来源:stackoverflow

时间:2024-04-19 18:57:33 127浏览 收藏

最近发现不少小伙伴都对Golang很感兴趣,所以今天继续给大家介绍Golang相关的知识,本文《Golang中根据对象值对JSON解析进行排序》主要内容涉及到等等知识点,希望能帮到你!当然如果阅读本文时存在不同想法,可以在评论中表达,但是请勿使用过激的措辞~

问题内容

尝试解析 json 并根据 struct 的值之一进行排序。 我想根据custom_meta的part_num对json进行排序,我们如何做到这一点。代码如下:

type Maininfo struct {
    Id   string     `json:"id"`
    Meta []Metainfo `json:"meta"`
}


type Metainfo struct {
    Filename     string `json:"filename"`
    Custom_meta  string `json:"custom_meta"`
    Size         int    `json:"size"`
    Content_hash string `json:"content_hash"`
}

type Custom_meta struct {
    Part_num string `json:"part_num"`
    Part     int
}

func getMeta(body []byte) (*Maininfo, error) {
    var s = new(Maininfo)
    err := json.Unmarshal(body, &s)
    if err != nil {
        fmt.Println("whoops:", err)
    }
    return s, err
}


func getMetainfo(body []byte) (*Metainfo, error) {
    var s = new(Metainfo)
    err := json.Unmarshal(body, &s)
    if err != nil {
        fmt.Println("error", err)
    }
    return s, err
}

type AxisSorter []Metainfo

func (a AxisSorter) Len() int           { return len(a) }
func (a AxisSorter) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a AxisSorter) Less(i, j int) bool { return a[i].Custom_meta < a[j].Custom_meta }


type NameSorter []Metainfo

func (a NameSorter) Len() int           { return len(a) }
func (a NameSorter) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a NameSorter) Less(i, j int) bool { return a[i].Custom_meta < a[j].Custom_meta }

func main() {
s, err := getMeta([]byte(body))
    fmt.Println("Main stuff", s)

    var metaInfo []Metainfo
    metaInfo = s.Meta
}
    var customMeta CustomMeta

    sort.Sort(AxisSorter(metaInfo))
    fmt.Println("metaInfo sorted ", metaInfo)

    sort.Sort(NameSorter(metaInfo))
    fmt.Println("metaInfo sorted 2 ", metaInfo)

    sort.Slice(metaInfo, func(i, j int) bool {
        fmt.Println("meta ", metaInfo[i].Custom_meta)
        return metaInfo[i].Custom_meta < metaInfo[j].Custom_meta
      })

}

我无法根据part_num对代码进行排序,我们该怎么做,因为info不是一个单独的对象,它是一个字符串。我们如何解析字符串并根据 int 值对其进行排序。


解决方案


看起来这里的主要问题是“custom_meta”值是带引号的 json 字符串而不是嵌套对象,这意味着它无法被解组到具有(大概)所需“part_num”整数的对象中。 p>

理想情况下,您可以修复此数据的来源,以便它发出 json 对象而不是带引号的 json 字符串;但是,如果这不可行,那么您可以执行以下操作。

  1. 首先取消引用源字符串,然后照常进行解组,让“custom_meta”类型实现 json.Umarshaler
  2. 按嵌套的“custom_meta.part”字段单独对“maininfo.meta”进行排序,或作为该类型的自定义解组器的一部分。

例如(Go Playground):

type maininfo struct {
  id        string     `json:"id"`
  metainfos []metainfo `json:"meta"`
}

type metainfo struct {
  filename    string     `json:"filename"`
  custom      custommeta `json:"custom_meta"`
  size        int        `json:"size"`
  contenthash string     `json:"content_hash"`
}

type custommeta struct {
  partnum int `json:"part_num"`
}

func (cm *custommeta) unmarshaljson(bs []byte) error {
  // unquote the source string so we can unmarshal it.
  unquoted, err := strconv.unquote(string(bs))
  if err != nil {
    return err
  }

  // create an aliased type so we can use the default unmarshaler.
  type custommeta2 custommeta
  var cm2 custommeta2

  // unmarshal the unquoted string and assign to the original object.
  if err := json.unmarshal([]byte(unquoted), &cm2); err != nil {
    return err
  }
  *cm = custommeta(cm2)
  return nil
}

然后你可以像这样解析后排序:

var doc MainInfo
err := json.Unmarshal([]byte(jsonstr), &doc)
if err != nil {
  panic(err)
}
sort.Slice(doc.MetaInfos, func(i, j int) bool {
  p1 := doc.MetaInfos[i].Custom.PartNum
  p2 := doc.MetaInfos[j].Custom.PartNum
  return p1 < p2
})

当然,您也可以将排序作为“maininfo”类型的自定义 unmarshaljson 方法的一部分来执行。

本篇关于《Golang中根据对象值对JSON解析进行排序》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于Golang的相关知识,请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>