https://github.com/genelet/determined
Build customized JSON and HCL Unmarshaler with Determined
https://github.com/genelet/determined
golang hcl json
Last synced: 5 months ago
JSON representation
Build customized JSON and HCL Unmarshaler with Determined
- Host: GitHub
- URL: https://github.com/genelet/determined
- Owner: genelet
- License: mit
- Created: 2022-04-26T14:39:13.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2025-12-03T23:04:25.000Z (7 months ago)
- Last Synced: 2025-12-04T22:29:56.324Z (7 months ago)
- Topics: golang, hcl, json
- Language: Go
- Homepage: https://medium.com/@peterbi_91340/decoding-of-dynamic-json-data-1d4e67318661
- Size: 399 KB
- Stars: 24
- Watchers: 1
- Forks: 3
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# determined
_Determined_ marshals and unmarshals JSON data to _go struct_ containing interfaces determined at run-time.
[](https://godoc.org/github.com/genelet/determined)
> **Note**: The HCL parsing feature has been extracted and moved to a separate Github package [github.com/genelet/horizon](https://github.com/genelet/horizon). The old HCL code in this package is frozen for compatibility reasons.
## Installation
```bash
go get github.com/genelet/determined
```
## Introduction
The core Golang package `encoding/json` is an exceptional library for managing JSON data. However, to decode the interface type, it necessitates writing a customized `Unmarshaler` for the target object. While this isn’t typically a challenging task, it often results in repetitive code for different types of objects and packages.
Therefore, `determined` was created to streamline the coding process and enhance productivity.
## Usage
To decode JSON to an object containing interface types, use `det.JsonUnmarshal`.
```go
// JsonUnmarshal unmarshals JSON data with interfaces determined by spec.
//
// - dat: JSON data
// - current: object as pointer
// - spec: *schema.Struct
// - ref: struct map, with key being string name and value reference to struct
func JsonUnmarshal(dat []byte, current interface{}, spec *schema.Struct, ref map[string]interface{}) error
```
You first need to define the structure of your interfaces using `schema.NewStruct` from the [github.com/genelet/schema](https://github.com/genelet/schema) package.
### Example
Here is an example of how to use `determined` to decode JSON data where fields are interfaces.
```go
package main
import (
"fmt"
"github.com/genelet/determined/det"
"github.com/genelet/schema"
)
type geo struct {
Name string `json:"name"`
Shape inter `json:"shape"`
}
type inter interface {
Area() float32
}
type square struct {
SX int `json:"sx"`
SY int `json:"sy"`
}
func (self *square) Area() float32 {
return float32(self.SX * self.SY)
}
type circle struct {
Radius float32 `json:"radius"`
}
func (self *circle) Area() float32 {
return 3.14159 * self.Radius
}
type toy struct {
Geo geo `json:"geo"`
ToyName string `json:"toy_name"`
Price float32 `json:"price"`
}
type child struct {
Brand map[string]*toy `json:"brand"`
Age int `json:"age"`
}
func main() {
data1 := `{
"age" : 5,
"brand" : {
"abc1" : {
"toy_name" : "roblox",
"price" : 99.9,
"geo" : {
"name" : "medium shape",
"shape" : { "radius" : 1.234 }
}
},
"def2" : {
"toy_name" : "minecraft",
"price" : 9.9,
"geo" : {
"name" : "square shape",
"shape" : { "sx" : 5, "sy" : 6 }
}
}
}
}`
// Define the structure of the interfaces for the specific data
spec, err := schema.NewStruct(
"child", map[string]interface{}{
"Brand": map[string][2]interface{}{
"abc1":[2]interface{}{"toy", map[string]interface{}{
"Geo": [2]interface{}{
"geo", map[string]interface{}{"Shape": "circle"}}}},
"def2":[2]interface{}{"toy", map[string]interface{}{
"Geo": [2]interface{}{
"geo", map[string]interface{}{"Shape": "square"}}}},
},
},
)
if err != nil {
panic(err)
}
// Map string names to actual struct pointers
ref := map[string]interface{}{
"toy": &toy{},
"geo": &geo{},
"circle": &circle{},
"square": &square{},
}
c := new(child)
err = det.JsonUnmarshal([]byte(data1), c, spec, ref)
if err != nil {
panic(err)
}
fmt.Printf("Age: %v\n", c.Age)
fmt.Printf("Brand abc1: %#v\n", c.Brand["abc1"])
fmt.Printf("Brand abc1 Shape: %#v\n", c.Brand["abc1"].Geo.Shape)
fmt.Printf("Brand def2: %#v\n", c.Brand["def2"])
fmt.Printf("Brand def2 Shape: %#v\n", c.Brand["def2"].Geo.Shape)
}
```
For more details on how to construct the `spec` using `NewStruct`, please refer to [DOCUMENT.md](DOCUMENT.md).