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

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

Patricia Arquette
Patricia ArquetteOriginal
2024-12-19 10:49:12342browse

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

Unmarshaling Dynamic JSON Based on a Type Key Without Introducing Generic Fields

Many structured JSON data require unmarshalling into Go structs, often containing nested fields with varying data types. When a nested field's data type varies based on a type key within the JSON, conventional methods of unmarshalling using custom fields can lead to unnecessary boilerplate code.

In this context, let's consider the following JSON spec:

{
  "some_data": "foo",
  "dynamic_field": { "type": "A", "name": "Johnny" },
  "other_data": "bar"
}

and

{
  "some_data": "foo",
  "dynamic_field": { "type": "B", "address": "Somewhere" },
  "other_data": "bar"
}

Both these JSON documents should be unmarshalled into the same Go struct:

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

The challenge lies in defining the 'Something' type that can accommodate dynamic data based on the 'type' key within the 'dynamic_field' object.

To avoid the need for an explicit 'generic' field (e.g., Value, Data), we can leverage the power of type embedding and interfaces.

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

type DynamicType struct {
  Value interface{}
}

Within the 'DynamicType,' the 'Value' field can hold any type of data, based on the 'type' key in the JSON. To facilitate proper unmarshalling, we implement the UnmarshalJSON method on the 'DynamicType':

func (d *DynamicType) UnmarshalJSON(data []byte) error {
    var typ struct {
        Type string `json:"type"`
    }
    if err := json.Unmarshal(data, &typ); err != nil {
        return err
    }
    switch typ.Type {
    case "A":
        d.Value = new(TypeA)
    case "B":
        d.Value = new(TypeB)
    }
    return json.Unmarshal(data, d.Value)
}

We define specific types for different types of data:

type TypeA struct {
    Name string `json:"name"`
}

type TypeB struct {
    Address string `json:"address"`
}

With this approach, we can unmarshal the JSON documents without the need for an additional generic field, allowing us to maintain a clean and extensible data structure.

The above is the detailed content of How to Unmarshal Dynamic JSON in Go Based on a Type Key Without Generic Fields?. 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