Сортировка синтаксического анализа JSON по значению объекта в Golang - PullRequest
0 голосов
/ 12 сентября 2018

Попытка синтаксического анализа json и сортировки по одному из значений struct. Я хочу отсортировать JSON на основе part_num custom_meta, как мы можем это сделать. Код выглядит следующим образом:

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, как мы можем это сделать, так как информация не является отдельным объектом, это строка. Как мы можем разобрать строку и отсортировать ее по значению int.

1 Ответ

0 голосов
/ 13 сентября 2018

Похоже, основная проблема здесь заключается в том, что значение «custom_meta» является строкой JSON в кавычках, а не вложенным объектом, что означает, что его нельзя преобразовать в объект с (предположительно) желаемым целым числом «part_num».

В идеале вы могли бы исправить источник этих данных так, чтобы они испускали объект JSON вместо строки JSON в кавычках; однако, если это невозможно, вы можете сделать следующее.

  1. Имейте тип "Custom_meta", реализующий json.Umarshaler, сначала отменив кавычки исходной строки, а затем, как обычно, удалите маршалинг.
  2. Сортировать «Maininfo.Meta» по вложенному полю «Custom_meta.Part» отдельно или как часть пользовательского демаршалера для этого типа.

Например ( 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
})

Конечно, вы также можете выполнить сортировку как часть пользовательского UnmarshalJSON метода для типа «MainInfo».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...