Немаршаллирование массивов json как объектов json - PullRequest
0 голосов
/ 04 июня 2018

Мне нужно демонтировать ряд объектов Json, но один из объектов содержит массив json, который на самом деле не очень хорошо структурирован.

"labels": [
    {
      "key": "owner",
      "value": "harry"
    },
    {
      "key": "group",
      "value": "student"
    }
  ]

Я демонтирую его, используя эту структуру -

type StudentDetails struct {
Id        string         `json:"id"`
Name      string         `json:"name"`
Labels    []Label   `json:"labels,omitempty"`
}
type Label struct {
Key string `json:"key"`
Value string `json:"value"`
}

И я должен получить к нему доступ, используя x.Labels [0] .key == "owner" внутри цикла for, что очень раздражает.Я хочу иметь возможность сделать x.Labels.Owner == "Гарри" вместо этого.Как мне добиться этого?Остальная часть JSON отлично справляется с использованием функции unmarshal по умолчанию, поэтому я не думаю, что написание пользовательской функции будет хорошим вариантом.

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

С имеющимися здесь ограничениями это примерно так же близко, как вы получите ( бег на детской площадке ):

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    j := `
        {
            "id": "42",
            "name": "Marvin",
            "labels": [
                {
                    "key": "owner",
                    "value": "harry"
                },
                {
                    "key": "group",
                    "value": "student"
                }
            ]
        }`

    d := StudentDetails{}
    err := json.Unmarshal([]byte(j), &d)
    if err != nil {
        panic(err)
    }
    fmt.Println(d.Labels["owner"])
    fmt.Println(d.Labels["group"])
}

type StudentDetails struct {
    Id     string `json:"id"`
    Name   string `json:"name"`
    Labels Labels `json:"labels"`
}

type Labels map[string]string

func (l *Labels) UnmarshalJSON(b []byte) error {
    a := []map[string]string{}
    err := json.Unmarshal(b, &a)
    if err != nil {
        return err
    }

    t := map[string]string{}
    for _, m := range a {
        t[m["key"]] = m["value"]
    }
    *l = t
    return nil
}
0 голосов
/ 04 июня 2018

Как насчет определения пользовательского типа []Label и добавления к нему функции.

Например,

type Labels []Label

func (l Labels) Owner() string {
    if len(l) > 1 {
        return l[0].Value
    }
    return ""
}
...