Bagaimana untuk Meratakan Medan Antara Muka Tanpa Nama dalam Pensirian Go JSON?

Susan Sarandon
Lepaskan: 2024-10-29 06:52:02
asal
360 orang telah melayarinya

How to Flatten Anonymous Interface Fields in Go JSON Serialization?

Meratakan Struktur JSON dengan Ahli Tanpa Nama dalam Go

Dalam Go, medan struct tanpa nama lazimnya disusun seolah-olah medan yang dieksport dalamannya ialah medan dalam struct luar. Walau bagaimanapun, ini boleh membawa kepada tingkah laku yang tidak dijangka apabila menyusun struct dengan ahli tanpa nama jenis antara muka{}.

Masalahnya

Pertimbangkan contoh berikut:

<code class="go">type User struct {
    Id   int    `json:"id"`
    Name string `json:"name"`
}

type Session struct {
    Id     int `json:"id"`
    UserId int `json:"userId"`
}

type Anything interface{}

type Hateoas struct {
    Anything
    Links map[string]string `json:"_links"`
}

func MarshalHateoas(subject interface{}) ([]byte, error) {
    h := &Hateoas{subject, make(map[string]string)}
    switch s := subject.(type) {
    case *User:
        h.Links["self"] = fmt.Sprintf("http://user/%d", s.Id)
    case *Session:
        h.Links["self"] = fmt.Sprintf("http://session/%d", s.Id)
    }
    return json.MarshalIndent(h, "", "    ")
}

func main() {
    u := &User{123, "James Dean"}
    s := &Session{456, 123}
    json, err := MarshalHateoas(u)
    if err != nil {
        panic(err)
    } else {
        fmt.Println("User JSON:")
        fmt.Println(string(json))
    }
    json, err = MarshalHateoas(s)
    if err != nil {
        panic(err)
    } else {
        fmt.Println("Session JSON:")
        fmt.Println(string(json))
    }
}</code>
Salin selepas log masuk

Apabila berjalan kod ini, JSON yang terhasil tidak seperti yang dijangkakan:

<code class="json">User JSON:
{
    "Anything": {
        "id": 123,
        "name": "James Dean"
    },
    "_links": {
        "self": "http://user/123"
    }
}
Session JSON:
{
    "Anything": {
        "id": 456,
        "userId": 123
    },
    "_links": {
        "self": "http://session/456"
    }
}</code>
Salin selepas log masuk

Seperti yang anda lihat, ahli tanpa nama Anything dianggap sebagai medan bernama dalam JSON, yang bukan tingkah laku yang dimaksudkan.

Penyelesaian

Untuk meratakan ahli tanpa nama dan mencapai struktur JSON yang diingini, kita boleh menggunakan pakej reflect untuk menggelungkan medan struct dan memetakannya ke peta[rentetan]antara muka{}. Ini membolehkan kami mengekalkan struktur rata bagi struktur asal tanpa memperkenalkan medan baharu.

Kod yang dikemas kini adalah seperti berikut:

<code class="go">import (
    "encoding/json"
    "fmt"
    "reflect"
)

// ... (rest of the code remains the same)

func MarshalHateoas(subject interface{}) ([]byte, error) {
    links := make(map[string]string)
    out := make(map[string]interface{})
    subjectValue := reflect.Indirect(reflect.ValueOf(subject))
    subjectType := subjectValue.Type()
    for i := 0; i < subjectType.NumField(); i++ {
        field := subjectType.Field(i)
        name := subjectType.Field(i).Name
        out[field.Tag.Get("json")] = subjectValue.FieldByName(name).Interface()
    }

    switch s := subject.(type) {
    case *User:
        links["self"] = fmt.Sprintf("http://user/%d", s.Id)
    case *Session:
        links["self"] = fmt.Sprintf("http://session/%d", s.Id)
    }

    out["_links"] = links
    return json.MarshalIndent(out, "", "    ")
}</code>
Salin selepas log masuk

Dengan pengubahsuaian ini, JSON yang terhasil diratakan dengan betul:

<code class="json">User JSON:
{
    "id": 123,
    "name": "James Dean",
    "_links": {
        "self": "http://user/123"
    }
}
Session JSON:
{
    "id": 456,
    "userId": 123,
    "_links": {
        "self": "http://session/456"
    }
}</code>
Salin selepas log masuk

Atas ialah kandungan terperinci Bagaimana untuk Meratakan Medan Antara Muka Tanpa Nama dalam Pensirian Go JSON?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!