Convert Figma logo to code with AI

Jeffail logogabs

For parsing, creating and editing unknown or dynamic JSON in Go

3,445
201
3,445
37

Top Related Projects

Fast JSON parser and validator for Go. No custom structs, no code generation, no reflection

14,102

Get JSON values quickly - JSON parser for Go

One of the fastest alternative JSON parser for Go that does not require schema

a Go package to interact with arbitrary JSON

Fast JSON serializer for golang.

13,330

A high-performance 100% compatible drop-in replacement of "encoding/json"

Quick Overview

Gabs (Go Advanced Buffered Scanner) is a small utility library for parsing, creating, and editing unknown JSON in Go. It provides a simple API for dynamically navigating and manipulating JSON structures without the need for predefined structs, making it particularly useful for working with dynamic or unpredictable JSON data.

Pros

  • Easy to use API for parsing and manipulating JSON
  • Supports dynamic JSON navigation without predefined structs
  • Efficient memory usage with buffered scanning
  • Allows for creation and editing of JSON structures

Cons

  • Limited to JSON data format only
  • May be less performant than struct-based parsing for known JSON structures
  • Lacks some advanced features found in larger JSON libraries
  • Documentation could be more comprehensive

Code Examples

  1. Parsing JSON and accessing values:
jsonParsed, _ := gabs.ParseJSON([]byte(`{"name":{"first":"Tom","last":"Anderson"},"age":37}`))
firstName := jsonParsed.Path("name.first").Data().(string)
fmt.Println(firstName) // Output: Tom
  1. Creating and modifying JSON:
json := gabs.New()
json.Set(10, "numbers", "1")
json.Set(20, "numbers", "2")
json.Set(30, "numbers", "3")
fmt.Println(json.String()) // Output: {"numbers":{"1":10,"2":20,"3":30}}
  1. Working with arrays:
jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":["a","b","c"]}`))
jsonParsed.ArrayAppend("d", "array")
fmt.Println(jsonParsed.Path("array").Index(3).Data().(string)) // Output: d

Getting Started

To use Gabs in your Go project, first install it:

go get github.com/Jeffail/gabs/v2

Then import it in your Go code:

import "github.com/Jeffail/gabs/v2"

Now you can start using Gabs to parse and manipulate JSON:

jsonObj, _ := gabs.ParseJSON([]byte(`{"name":"John","age":30}`))
name := jsonObj.Path("name").Data().(string)
fmt.Println(name) // Output: John

Competitor Comparisons

Fast JSON parser and validator for Go. No custom structs, no code generation, no reflection

Pros of fastjson

  • Significantly faster JSON parsing and encoding
  • Lower memory usage and fewer allocations
  • Supports streaming JSON processing for large datasets

Cons of fastjson

  • Less feature-rich API compared to gabs
  • Requires more manual handling of JSON structures
  • Limited support for modifying existing JSON objects

Code Comparison

gabs:

jsonObj, _ := gabs.ParseJSON([]byte(`{"name":"John","age":30}`))
name := jsonObj.Path("name").Data().(string)
jsonObj.Set(31, "age")

fastjson:

var p fastjson.Parser
v, _ := p.Parse(`{"name":"John","age":30}`)
name := string(v.GetStringBytes("name"))
v.Set("age", fastjson.MustParse("31"))

Both libraries provide JSON parsing and manipulation capabilities, but they differ in their approach and performance characteristics. gabs offers a more user-friendly API with convenient methods for accessing and modifying JSON data, while fastjson focuses on high-performance parsing and encoding at the cost of a slightly more complex API.

fastjson is particularly well-suited for applications that require fast processing of large JSON datasets or have strict performance requirements. On the other hand, gabs may be more appropriate for projects where ease of use and a rich feature set are prioritized over raw performance.

14,102

Get JSON values quickly - JSON parser for Go

Pros of gjson

  • Faster performance for parsing and retrieving JSON data
  • More extensive query syntax for complex JSON operations
  • Supports modifying JSON data with Get-Set-Get pattern

Cons of gjson

  • Limited JSON creation capabilities compared to gabs
  • Less intuitive for building JSON structures from scratch
  • Steeper learning curve for advanced query syntax

Code Comparison

gabs example:

jsonObj := gabs.New()
jsonObj.Set(10, "foo", "bar", "baz")
jsonObj.Set(20, "foo", "bar", "qux")
fmt.Println(jsonObj.String())

gjson example:

json := `{"foo":{"bar":{"baz":10,"qux":20}}}`
value := gjson.Get(json, "foo.bar.baz")
fmt.Println(value.Int())

Both libraries offer JSON parsing and manipulation capabilities, but they have different strengths. gabs excels in creating and modifying JSON structures, while gjson focuses on fast parsing and querying of existing JSON data. The choice between them depends on the specific requirements of your project, such as performance needs, JSON creation vs. parsing, and the complexity of operations you need to perform on JSON data.

One of the fastest alternative JSON parser for Go that does not require schema

Pros of jsonparser

  • Faster performance, especially for large JSON files
  • Lower memory usage due to not creating intermediate objects
  • Supports streaming JSON parsing

Cons of jsonparser

  • Less intuitive API for complex operations
  • Limited support for modifying JSON structures
  • Requires more manual handling of data types

Code Comparison

jsonparser:

data := []byte(`{"name": "John", "age": 30}`)
name, err := jsonparser.GetString(data, "name")
age, err := jsonparser.GetInt(data, "age")

gabs:

jsonParsed, err := gabs.ParseJSON([]byte(`{"name": "John", "age": 30}`))
name := jsonParsed.Path("name").Data().(string)
age := jsonParsed.Path("age").Data().(float64)

Summary

jsonparser is optimized for performance and memory efficiency, making it ideal for processing large JSON files or high-throughput applications. It excels in scenarios where speed and resource conservation are crucial.

gabs offers a more user-friendly API for complex JSON manipulations and modifications. It's better suited for applications that require frequent JSON structure alterations or when ease of use is prioritized over raw performance.

Choose jsonparser for high-performance, read-heavy operations on large JSON datasets. Opt for gabs when working with smaller JSON structures or when frequent modifications and a more intuitive API are needed.

a Go package to interact with arbitrary JSON

Pros of go-simplejson

  • Simpler API with fewer methods, making it easier to learn and use
  • More flexible for handling unknown JSON structures
  • Better support for chaining operations

Cons of go-simplejson

  • Less performant than gabs for large JSON documents
  • Fewer advanced features and manipulation options
  • Limited support for creating or modifying JSON structures

Code Comparison

go-simplejson:

js, _ := simplejson.NewJson([]byte(`{"name":"John","age":30}`))
name, _ := js.Get("name").String()
age, _ := js.Get("age").Int()

gabs:

jsonParsed, _ := gabs.ParseJSON([]byte(`{"name":"John","age":30}`))
name := jsonParsed.Path("name").Data().(string)
age := jsonParsed.Path("age").Data().(float64)

Both libraries provide ways to parse and access JSON data, but gabs offers more advanced features for manipulation and creation of JSON structures. go-simplejson is simpler to use and more flexible for handling unknown JSON structures, while gabs is more performant and feature-rich. The choice between them depends on the specific requirements of your project, such as performance needs, JSON manipulation complexity, and ease of use.

Fast JSON serializer for golang.

Pros of easyjson

  • Generates code for faster JSON encoding/decoding, resulting in better performance
  • Supports custom MarshalJSON/UnmarshalJSON methods for fine-grained control
  • Integrates well with Go's standard encoding/json package

Cons of easyjson

  • Requires code generation step, which adds complexity to the build process
  • Less flexible for dynamic JSON manipulation compared to gabs
  • Steeper learning curve for newcomers due to code generation approach

Code Comparison

easyjson:

//easyjson:json
type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

gabs:

jsonParsed, _ := gabs.ParseJSON([]byte(`{"name":"John","age":30}`))
name := jsonParsed.Path("name").Data().(string)
age := jsonParsed.Path("age").Data().(float64)

Summary

easyjson focuses on performance through code generation, making it ideal for projects with known JSON structures and high-performance requirements. gabs, on the other hand, offers more flexibility for dynamic JSON manipulation without code generation. Choose easyjson for speed and static typing, or gabs for ease of use and dynamic JSON handling.

13,330

A high-performance 100% compatible drop-in replacement of "encoding/json"

Pros of json-iterator/go

  • Significantly faster JSON parsing and serialization
  • Drop-in replacement for the standard library's encoding/json
  • Supports custom extensions and configurations

Cons of json-iterator/go

  • Less intuitive for complex JSON manipulation
  • Requires more setup for advanced use cases

Code Comparison

json-iterator/go:

import jsoniter "github.com/json-iterator/go"

var json = jsoniter.ConfigCompatibleWithStandardLibrary
data := json.Get(input, "users", 0, "name").ToString()

gabs:

import "github.com/Jeffail/gabs/v2"

jsonParsed, _ := gabs.ParseJSON([]byte(input))
data, _ := jsonParsed.Path("users.0.name").Data().(string)

Key Differences

  • json-iterator/go focuses on performance and compatibility with the standard library
  • gabs provides a more intuitive API for JSON manipulation and querying
  • json-iterator/go is better suited for high-performance applications
  • gabs is more convenient for complex JSON operations and data extraction

Use Cases

  • Choose json-iterator/go for applications requiring high-speed JSON processing
  • Opt for gabs when working with complex JSON structures and frequent data manipulation

Both libraries have their strengths, and the choice depends on specific project requirements and performance needs.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Gabs

pkg.go for Jeffail/gabs

Gabs is a small utility for dealing with dynamic or unknown JSON structures in Go. It's pretty much just a helpful wrapper for navigating hierarchies of map[string]interface{} objects provided by the encoding/json package. It does nothing spectacular apart from being fabulous.

If you're migrating from version 1 check out migration.md for guidance.

Use

Import

Using modules:

import (
	"github.com/Jeffail/gabs/v2"
)

Without modules:

import (
	"github.com/Jeffail/gabs"
)

Parsing and searching JSON

jsonParsed, err := gabs.ParseJSON([]byte(`{
	"outer":{
		"inner":{
			"value1":10,
			"value2":22
		},
		"alsoInner":{
			"value1":20,
			"array1":[
				30, 40
			]
		}
	}
}`))
if err != nil {
	panic(err)
}

var value float64
var ok bool

value, ok = jsonParsed.Path("outer.inner.value1").Data().(float64)
// value == 10.0, ok == true

value, ok = jsonParsed.Search("outer", "inner", "value1").Data().(float64)
// value == 10.0, ok == true

value, ok = jsonParsed.Search("outer", "alsoInner", "array1", "1").Data().(float64)
// value == 40.0, ok == true

gObj, err := jsonParsed.JSONPointer("/outer/alsoInner/array1/1")
if err != nil {
	panic(err)
}
value, ok = gObj.Data().(float64)
// value == 40.0, ok == true

value, ok = jsonParsed.Path("does.not.exist").Data().(float64)
// value == 0.0, ok == false

exists := jsonParsed.Exists("outer", "inner", "value1")
// exists == true

exists = jsonParsed.ExistsP("does.not.exist")
// exists == false

Iterating objects

jsonParsed, err := gabs.ParseJSON([]byte(`{"object":{"first":1,"second":2,"third":3}}`))
if err != nil {
	panic(err)
}

// S is shorthand for Search
for key, child := range jsonParsed.S("object").ChildrenMap() {
	fmt.Printf("key: %v, value: %v\n", key, child.Data().(float64))
}

Iterating arrays

jsonParsed, err := gabs.ParseJSON([]byte(`{"array":["first","second","third"]}`))
if err != nil {
	panic(err)
}

for _, child := range jsonParsed.S("array").Children() {
	fmt.Println(child.Data().(string))
}

Will print:

first
second
third

Children() will return all children of an array in order. This also works on objects, however, the children will be returned in a random order.

Searching through arrays

If your structure contains arrays you must target an index in your search.

jsonParsed, err := gabs.ParseJSON([]byte(`{"array":[{"value":1},{"value":2},{"value":3}]}`))
if err != nil {
	panic(err)
}
fmt.Println(jsonParsed.Path("array.1.value").String())

Will print 2.

Generating JSON

jsonObj := gabs.New()
// or gabs.Wrap(jsonObject) to work on an existing map[string]interface{}

jsonObj.Set(10, "outer", "inner", "value")
jsonObj.SetP(20, "outer.inner.value2")
jsonObj.Set(30, "outer", "inner2", "value3")

fmt.Println(jsonObj.String())

Will print:

{"outer":{"inner":{"value":10,"value2":20},"inner2":{"value3":30}}}

To pretty-print:

fmt.Println(jsonObj.StringIndent("", "  "))

Will print:

{
  "outer": {
    "inner": {
      "value": 10,
      "value2": 20
    },
    "inner2": {
      "value3": 30
    }
  }
}

Generating Arrays

jsonObj := gabs.New()

jsonObj.Array("foo", "array")
// Or .ArrayP("foo.array")

jsonObj.ArrayAppend(10, "foo", "array")
jsonObj.ArrayAppend(20, "foo", "array")
jsonObj.ArrayAppend(30, "foo", "array")

fmt.Println(jsonObj.String())

Will print:

{"foo":{"array":[10,20,30]}}

Working with arrays by index:

jsonObj := gabs.New()

// Create an array with the length of 3
jsonObj.ArrayOfSize(3, "foo")

jsonObj.S("foo").SetIndex("test1", 0)
jsonObj.S("foo").SetIndex("test2", 1)

// Create an embedded array with the length of 3
jsonObj.S("foo").ArrayOfSizeI(3, 2)

jsonObj.S("foo").Index(2).SetIndex(1, 0)
jsonObj.S("foo").Index(2).SetIndex(2, 1)
jsonObj.S("foo").Index(2).SetIndex(3, 2)

fmt.Println(jsonObj.String())

Will print:

{"foo":["test1","test2",[1,2,3]]}

Converting back to JSON

This is the easiest part:

jsonParsedObj, _ := gabs.ParseJSON([]byte(`{
	"outer":{
		"values":{
			"first":10,
			"second":11
		}
	},
	"outer2":"hello world"
}`))

jsonOutput := jsonParsedObj.String()
// Becomes `{"outer":{"values":{"first":10,"second":11}},"outer2":"hello world"}`

And to serialize a specific segment is as simple as:

jsonParsedObj := gabs.ParseJSON([]byte(`{
	"outer":{
		"values":{
			"first":10,
			"second":11
		}
	},
	"outer2":"hello world"
}`))

jsonOutput := jsonParsedObj.Search("outer").String()
// Becomes `{"values":{"first":10,"second":11}}`

Merge two containers

You can merge a JSON structure into an existing one, where collisions will be converted into a JSON array.

jsonParsed1, _ := ParseJSON([]byte(`{"outer":{"value1":"one"}}`))
jsonParsed2, _ := ParseJSON([]byte(`{"outer":{"inner":{"value3":"three"}},"outer2":{"value2":"two"}}`))

jsonParsed1.Merge(jsonParsed2)
// Becomes `{"outer":{"inner":{"value3":"three"},"value1":"one"},"outer2":{"value2":"two"}}`

Arrays are merged:

jsonParsed1, _ := ParseJSON([]byte(`{"array":["one"]}`))
jsonParsed2, _ := ParseJSON([]byte(`{"array":["two"]}`))

jsonParsed1.Merge(jsonParsed2)
// Becomes `{"array":["one", "two"]}`

Parsing Numbers

Gabs uses the json package under the bonnet, which by default will parse all number values into float64. If you need to parse Int values then you should use a json.Decoder:

sample := []byte(`{"test":{"int":10,"float":6.66}}`)
dec := json.NewDecoder(bytes.NewReader(sample))
dec.UseNumber()

val, err := gabs.ParseJSONDecoder(dec)
if err != nil {
    t.Errorf("Failed to parse: %v", err)
    return
}

intValue, err := val.Path("test.int").Data().(json.Number).Int64()