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
Release: 2024-12-19 10:49:12
Original
321 people have browsed it

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"
}
Copy after login

and

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

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"`
}
Copy after login

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{}
}
Copy after login

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)
}
Copy after login

We define specific types for different types of data:

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

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

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!

source:php.cn
Statement of this Website
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
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template