Go JSON 직렬화에서 익명 인터페이스 필드를 평면화하는 방법은 무엇입니까?

Susan Sarandon
풀어 주다: 2024-10-29 06:52:02
원래의
360명이 탐색했습니다.

How to Flatten Anonymous Interface Fields in Go JSON Serialization?

Go에서 익명 멤버를 사용하여 JSON 구조체 평면화

Go에서 익명 구조체 필드는 일반적으로 내부 내보낸 필드가 외부 구조체의 필드인 것처럼 마샬링됩니다. 그러나 이로 인해 인터페이스{} 유형의 익명 멤버로 구조체를 마샬링할 때 예기치 않은 동작이 발생할 수 있습니다.

문제

다음 예를 고려하세요.

<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>
로그인 후 복사

실행할 때 이 코드의 결과 JSON은 예상과 다릅니다.

<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>
로그인 후 복사

보시다시피 익명 멤버 Anything은 JSON에서 명명된 필드로 처리되는데 이는 의도한 동작이 아닙니다.

해결책

익명 멤버를 평면화하고 원하는 JSON 구조를 얻으려면 Reflect 패키지를 사용하여 구조체의 필드를 반복하고 이를 map[string]인터페이스{}에 매핑할 수 있습니다. 이를 통해 새 필드를 도입하지 않고도 원래 구조체의 평면 구조를 유지할 수 있습니다.

업데이트된 코드는 다음과 같습니다.

<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>
로그인 후 복사

이 수정을 통해 결과 JSON이 올바르게 평면화됩니다.

<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>
로그인 후 복사

위 내용은 Go JSON 직렬화에서 익명 인터페이스 필드를 평면화하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!