Home >Backend Development >Golang >How to Unmarshal Dynamic JSON Fields in Go Based on a Type Key?

How to Unmarshal Dynamic JSON Fields in Go Based on a Type Key?

Susan Sarandon
Susan SarandonOriginal
2024-12-05 20:17:10489browse

How to Unmarshal Dynamic JSON Fields in Go Based on a Type Key?

Unmarshal Dynamic JSON Based on a Type Key

Unmarshaling complex JSON data into a Go struct can be challenging when the JSON structure contains dynamic fields of varying types. This article addresses a specific scenario where the JSON fields hold mostly simple values, but occasionally a dynamic field with a specific type key determines the type of the field's value.

The goal is to create a Go struct with the same structure as the provided JSON, where the dynamic field is represented as an interface type, allowing for flexible handling based on its type.

One possible solution utilizes the following custom types:

type BigStruct struct {
    SomeData     string    `json:"some_data"`
    DynamicField Something `json:"dynamic_field"`
    OtherData    string    `json:"other_data"`
}

type Something interface {
    GetType() string
}

Then, create individual structs for each dynamic field type:

type BaseDynamicType struct {
    Type string `json:"type"`
}

type DynamicTypeA struct {
    BaseDynamicType
    Name string `json:"name"`
}

type DynamicTypeB struct {
    BaseDynamicType
    Address string `json:"address"`
}

func (d *BaseDynamicType) GetType() string {
    return d.Type
}

To unmarshal the JSON into this struct, the BigStruct can implement a custom UnmarshalJSON method:

func (b *BigStruct) UnmarshalJSON(data []byte) error {
    var tmp struct {
        SomeData     string          `json:"some_data"`
        DynamicField json.RawMessage `json:"dynamic_field"`
        OtherData    string          `json:"other_data"`
    }

    if err := json.Unmarshal(data, &tmp); err != nil {
        return err
    }
    b.Unmarshal(tmp.DynamicField)

    return nil
}

The Unmarshal method can be called from within UnmarshalJSON to parse the dynamic field:

func (b *BigStruct) Unmarshal(data json.RawMessage) error {
    switch UnmarshalledType(data) {
    case "A":
        var a DynamicTypeA
        if err := json.Unmarshal(data, &a); err != nil {
            return err
        }

        b.DynamicField = &a
    case "B":
        var b DynamicTypeB
        if err := json.Unmarshal(data, &b); err != nil {
            return err
        }

        b.DynamicField = &b
    }

    return nil
}

func UnmarshalledType(b json.RawMessage) string {
    var typ struct {
        Type string `json:"type"`
    }

    if err := json.Unmarshal(b, &typ); err != nil {
        log.Fatalf("Error extracting type from RawMessage: %v", err)
    }

    return typ.Type
}

With this approach, you can unmarshal dynamic JSON fields into the Go struct without introducing an additional placeholder field.

The above is the detailed content of How to Unmarshal Dynamic JSON Fields in Go Based on a Type Key?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn