Determined marshals and unmarshals JSON data to go struct containing interfaces determined at run-time.
Note: The HCL parsing feature has been extracted and moved to a separate Github package github.com/genelet/horizon. The old HCL code in this package is frozen for compatibility reasons.
go get github.com/genelet/determinedThe 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.
To decode JSON to an object containing interface types, use det.JsonUnmarshal.
// 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 structfuncJsonUnmarshal(dat []byte, currentinterface{}, spec*schema.Struct, refmap[string]interface{}) errorYou first need to define the structure of your interfaces using schema.NewStruct from the github.com/genelet/schema package.
Here is an example of how to use determined to decode JSON data where fields are interfaces.
package main
import (
"fmt""github.com/genelet/determined/det""github.com/genelet/schema"
)
typegeostruct {
Namestring`json:"name"`Shapeinter`json:"shape"`
}
typeinterinterface {
Area() float32
}
typesquarestruct {
SXint`json:"sx"`SYint`json:"sy"`
}
func (self*square) Area() float32 {
returnfloat32(self.SX*self.SY)
}
typecirclestruct {
Radiusfloat32`json:"radius"`
}
func (self*circle) Area() float32 {
return3.14159*self.Radius
}
typetoystruct {
Geogeo`json:"geo"`ToyNamestring`json:"toy_name"`Pricefloat32`json:"price"`
}
typechildstruct {
Brandmap[string]*toy`json:"brand"`Ageint`json:"age"`
}
funcmain() {
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 dataspec, 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"}}}},
},
},
)
iferr!=nil {
panic(err)
}
// Map string names to actual struct pointersref:=map[string]interface{}{
"toy": &toy{}, "geo": &geo{}, "circle": &circle{}, "square": &square{},
}
c:=new(child)
err=det.JsonUnmarshal([]byte(data1), c, spec, ref)
iferr!=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.