Code Monkey home page Code Monkey logo

hummus's Introduction

hummus

A concise way to declare structs and marshal them into JSON in Go.

Making nested structs/arrays in order to marshal JSON from objects can be such a pain sometimes, can't it? Especially when you are cherry-picking fields from one flat JSON message and trying to output them into another complex JSON message.

Well, along comes hummus which makes this super-duper easy. The biggest win, I feel, is that you can have all your nesting information in the same struct. Creating nested arrays and/or objects is a simple matter of using dots (.) or square brackets ([]) in your tags.

How to install

go get github.com/aditya87/hummus

Fetch dependencies

go get github.com/Jeffail/gabs
For testing
go get github.com/onsi/ginkgo/ginkgo
go get github.com/onsi/gomega

How to use

Marshalling JSON

...
type Info struct {
  Company           string `hummus:"company"`
	Address           string `hummus:"address"`
	Brand0Name        string `hummus:"brands[0].name"`
	Brand0Flavor      string `hummus:"brands[0].flavor"`
	Brand0Store0Name  string `hummus:"brands[0].stores[0].name"`
	Brand0Store0Price int    `hummus:"brands[0].stores[0].price,omitempty"`
	Brand0Store1Name  string `hummus:"brands[0].stores[1].name"`
	Brand0Store1Price int    `hummus:"brands[0].stores[1].price,omitempty"`
}

func main() {
  info := Info{
		Company:           "hello foods",
		Address:           "338 New St",
		Brand0Name:        "sabra",
		Brand0Flavor:      "jalapeno",
		Brand0Store0Name:  "safeway",
		Brand0Store0Price: 5,
		Brand0Store1Name:  "wholefoods",
		Brand0Store1Price: 10,
	}

	jsonOutput, err := hummus.Marshal(info)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(jsonOutput))
}

Gives us:

{
  "company": "hello foods",
  "address": "338 New St",
  "brands": [
    {
      "flavor": "jalapeno",
      "name": "sabra",
      "stores": [
        {
          "name": "safeway",
          "price": 5
        },
        {
          "name": "wholefoods",
          "price": 10
        }
      ]
    }
  ]
}

Translating one type of message into another

type Info struct {
	Name   string `json:"name" hummus:"name"`
	Flavor string `json:"flavor" hummus:"type"`

	MainSupplierName     string `json:"main_supplier_name" hummus:"suppliers[0].name"`
	MainSupplierLocation string `json:"main_supplier_location" hummus:"suppliers[0].location"`

	BackupSupplierName     string `json:"backup_supplier_name" hummus:"suppliers[1].name"`
	BackupSupplierLocation string `json:"backup_supplier_location" hummus:"suppliers[1].location"`
}

func main() {
	inputJSON := `{
		"name": "sabra",
		"flavor": "jalapeno",
		"main_supplier_name": "Hipster Foods",
		"main_supplier_location": "CO",
		"backup_supplier_name": "Good Foods",
		"backup_supplier_location": "CA"
	}`

	var input Info
	err := json.Unmarshal([]byte(inputJSON), &input)
	if err != nil {
		panic(err)
	}

	jsonOutput, err := hummus.Marshal(input)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(jsonOutput))
}

Gives us:

{
  "name": "sabra",
  "type": "jalapeno",
  "suppliers": [
    {
      "location": "CO",
      "name": "Hipster Foods"
    },
    {
      "location": "CA",
      "name": "Good Foods"
    }
  ]
}

Special cases

Escaping dots

Sometimes, you want to not interpret the dots in a JSON tag as hierarchical keys, instead you just want them to get interpreted as a flat key like so:

{
  "properties.name": "value"
}

Hummus offers you the ability to escape dots. Simply replace dots with hashtags in the struct tags:

...
type S struct {
	V string `hummus:"properties#name"`
}

func main() {
	s := S{
		V: "value",
	}

	jsonOutput, err := hummus.Marshal(s)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(jsonOutput))
}

This gives us:

{
  "properties.name": "value"
}

Which is the desired result.

Notes

  1. Also provided an omitempty option to ignore empty fields, just like the encoding/json library. e.g.:
type foo struct {
  bar string `hummus:"bar,omitempty"`
}
  1. Leverages reflect for dynamic struct interpretation and gabs for dynamic JSON generation.

Contributing

PRs are welcome. Make sure unit tests are run. To do so, firstly install the ginkgo and gomega libraries as described in the "fetch dependencies" section above. Then, simply run:

ginkgo -r .

In the main directory.

hummus's People

Contributors

davewalter avatar

Stargazers

. avatar Matt Cholick avatar Nat J. Bennett avatar

hummus's Issues

Fields without hummus tags can't follow fields with array hummus tags

Hi Adi,

Here's the description for our issue so you have it captured here:

Given a struct like:

type Config struct {
  OpsmanNetworkName string `json:"ops_manager_subnet" hummus:"networks_configuration.networks[0].name,omitempty"`
  OpsmanSubnetIDList []string `json:"ops_manager_subnet_list"` 
}

We receive the error invalid struct tag json:"ops_manager_subnet_list"
Looks like hummus assumes that the struct fields following a field with an “array” tag are also in the array.

It's also not ideal that fields with array tags must be defined in order of desired array index. It looks like this may be addressed along with the above issue, according to your README, so we'd like to +1 that.

Let us know if it would be better for us to fork this, or if you need more context.

Thanks!
Raina and Dave
PCF RelEng

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.