Skip to content

enrichman/polygo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Polygo

Polygo is a lightweight Go package for decoding polymorphic JSON responses effortlessly.

Dealing with APIs that return various types of objects can be challenging.
Polygo simplifies this process by allowing you to map your types into a common interface.

Example

Consider an API endpoint /v1/shapes that returns a list of shapes, each defined by a type field:

[
    { "type": "circle", "radius": 5 },
    { "type": "square", "side":   3 }
]

With Polygo, you can easily handle this polymorphic JSON response. Here's how.

  1. Create a Decoder: Initialize a decoder with a common interface and the field name used to check the object type.
  2. Register Types: Register your concrete types with the decoder.
  3. Unmarshal JSON: Use one of the available functions to unmarshal your JSON data.
// Define your shape interface
type Shape interface {
    Area() float64
}

// Create a decoder specifying the interface and the field name,
// and register your concrete types
decoder := polygo.NewDecoder[Shape]("type").
    Register("circle", Circle{}).
    Register("square", Square{})

// unmarshal your JSON
shapes, _ := decoder.UnmarshalArray(jsonBytes)

for _, shape := range shapes {
    // use the methods defined by the interface
    fmt.Printf("shape area: %v\n", shape.Area())

    // or check the concrete type if needed
    switch s := shape.(type) {
    case *Circle:
        fmt.Printf("circle radius: %v\n", s.Radius)
    case *Square:
        fmt.Printf("square side: %v\n", s.Side)
    }
}

Available functions

UnmarshalObject

UnmarshalObject will unmarshal a plain object:

jsonBody := []byte(`{ "type": "circle", "radius": 5 }`)

shape, err := decoder.UnmarshalObject(jsonBody)
if err != nil {
    return err
}

UnmarshalArray

UnmarshalArray will unmarshal an array of objects:

jsonBody := []byte(`[
    { "type": "circle", "radius": 5 },
    { "type": "square", "side": 3 }
]`)

shapes, err := decoder.UnmarshalArray(jsonBody)
if err != nil {
    return err
}

UnmarshalInnerObject

UnmarshalInnerObject will unmarshal an object, looking into the specified path (using the github.com/tidwall/gjson library).

jsonBody := []byte(`{
    "data": { "type": "circle", "radius": 5 }
}`)

shapes, err := decoder.UnmarshalInnerObject("data", jsonBody)
if err != nil {
    return err
}

UnmarshalInnerArray

UnmarshalInnerArray will unmarshal an array of objects, looking into the specified path (using the github.com/tidwall/gjson library).

jsonBody := []byte(`{
    "data": [
        { "type": "circle", "radius": 5 },
        { "type": "square", "side": 3 }
    ]
}`)

shapes, err := decoder.UnmarshalInnerArray("data", jsonBody)
if err != nil {
    return err
}

Wrapped response

If your data is wrapped in an object with fields that you are interested to check, you should use a struct with a json.RawMessage field. Then you can unmarshal this field with the decoder.

type Response struct {
    Code    int             `json:"code"`
    Message string          `json:"message"`
    Data    json.RawMessage `json:"data"`
}

jsonData := []byte(`{
    "code": 200,
    "message": "all good",
    "data": [
        { "type": "circle", "radius": 5 },
        { "type": "square", "side": 3 }
    ]
}`)

var resp Response
err := json.Unmarshal(jsonData, &resp)
if err != nil {
    return err
}

shapes, err := decoder.UnmarshalArray(resp.Data)
if err != nil {
    return err
}

Installation

To use Polygo in your Go project, simply import it:

import "github.com/enrichman/polygo"

Contributing

Contributions are welcome! Feel free to open issues or pull requests on GitHub.

License

MIT

Feedback

If you like the project please star it on Github 🌟, and feel free to drop me a note on Twitterhttps://twitter.com/enrichmann, or open an issue!

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages