A simple Go library to simplify working with JSON without the need to define structs.
Jogson requires Go version 1.18 or above.
To install the library use:
go get github.com/rmordechay/jogsonFor more information, see design.
object, err := jogson.NewObjectFromString(jsonString)
array, err := jogson.NewArrayFromString(jsonString)
mapper, err := jogson.NewMapperFromString(jsonString)object, err := jogson.NewObjectFromBytes(jsonBytes)
array, err := jogson.NewArrayFromBytes(jsonBytes)
mapper, err := jogson.NewMapperFromBytes(jsonBytes)object, err := jogson.NewObjectFromStruct(jsonStruct)
array, err := jogson.NewArrayFromStruct(jsonStruct)
mapper, err := jogson.NewMapperFromStruct(jsonStruct)mapper, err := jogson.NewMapperFromFile(jsonFilePath)
object, err := jogson.NewObjectFromFile(jsonFilePath)
array, err := jogson.NewArrayFromFile(jsonFilePath)Once you have an object, an array or a mapper, you can read the data easily. Consider the following JSON
jsonString := `{
"id": "748494b8-7d6e-4cad-8065-89e758797313",
"name": "Jason",
"age": 43,
"height": 1.87,
"is_funny": false,
"address": null,
"birthday": "1981-10-08",
"features": ["tall", "blue eyes", null],
"children": {
"Rachel": {"age": 15, "is_funny": false},
"Sara": {"age": 19, "is_funny": true}
}
}`Getting scalars - string, int, etc. - is similar both for object and array and only differ
in the parameter type (objects take string as key and arrays take int as index). You can get scalars by value or by reference, where the latter allows JSON null values. Nullable methods have
the suffix 'N' in their names.
By value:
// string
var name string = object.GetString("name") // Jason
// int
var age int = object.GetInt("age") // 15
// float64
var height float64 = object.GetFloat("height") // 1.87
// bool
var isFunny bool = object.GetBool("is_funny") // falseBy reference, which allows JSON null values (note the suffix 'N' at the end of the method names):
// string
var nameNullable *string = object.GetStringN("non-existent-key") // nil
// int
var ageNullable *int = object.GetIntN("non-existent-key") // nil
// float64
var heightNullable *float64 = object.GetFloatN("non-existent-key") // nil
// bool
var isFunnyNullable *bool = object.GetBoolN("non-existent-key") // nilBy value:
// string
var s string = array.GetString(0)
// int
var i int = array.GetInt(2)
// float64
var f float64 = array.GetFloat(5)
// bool
var b bool = array.GetBool(7)By reference, which allows JSON null values (Note the suffix 'N' at the end of the method names):
// string
var nameNullable *string = array.GetStringN(100) // nil
// int
var ageNullable *int = array.GetIntN(100) // nil
// float64
var heightNullable *float64 = array.GetFloatN(100) // nil
// bool
var isFunnyNullable *bool = array.GetBoolN(100) // nil// Check if a key exists
var keyExists bool = object.Contains("children")
// Check if the object is empty
var objectEmpty bool = object.IsEmpty()
// Get the object's size
var objectLen int = object.Length()
// Get object's keys
var keys []string = object.Keys()
// Get object's values
values := object.Values()
// Iterating over an object with key, value pair
children := object.GetObject("children")
for key, child := range children.Elements() {
fmt.Println("Child name:", key) // Rachel, Sara
fmt.Println(child.AsObject.GetInt("age")) // 15, 19
fmt.Println(child.AsObject.GetBool("is_funny")) // false, true
}You can also get the object as a map of strings by scalars (string, int, etc.) Values that
are JSON null will be returned as Go zero value. If you want to regard null values, call the
function with the suffix N (see next section). If a null was found, LastError will be set
and report a null conversion error. For more information, see error handling.
// Get the JsonObject as map of string and string
var stringMap map[string]string = object.AsStringMap()
// Get the JsonObject as map of string and int
var intMap map[string]int = object.AsIntMap()
// Get the JsonObject as map of string and float
var floatMap map[string]float64 = object.AsFloatMap()
// Get as a slice of JsonArray
var nestedArray map[string]JsonArray = object.AsArrayMap()
// Get as a slice of JsonObject
var objectArray map[string]JsonObject = object.AsObjectMap()If the object contains null values, and you want to represent that as nil value instead of zero value, you can
use one of the following functions that returns a pointer rather than a value which allows nil. This set of methods
do not set the LastError when a null value was found but instead returns it without reporting an error.
Note! This applies only for the scalar types. JsonObject and JsonArray will return an instance anyway,
and you should use the IsNull() method to check if they are null.
// Get the JsonObject as map of string and nullable strings
var nullableStringMap map[string]*string = object.AsStringMapN()
// Get the JsonObject as map of string and nullable ints
var nullableIntMap map[string]*int = object.AsIntMapN()
// Get the JsonObject as map of string and nullable floats
var nullableSloatMap map[string]*float64 = object.AsFloatMapN()// Get array from object
features := object.GetArray("features")
// Get features length
arrayLen := features.Length() // 2
// Get an element of features by index
secondElement := features.Get(1)
// Iterating over an array
for _, feature := range features.Elements() {
fmt.Println(feature.AsString) // tall, ...
}You can also get the array as a slice of scalars (string, int, etc.). Values that
are JSON null will be returned as Go zero value. If you want to regard null values, call the
function with the suffix N (see next section). If a null was found, LastError will be set
and report a null conversion error. For more information, see error handling.
// Get the JsonArray as a slice of string
var stringArray []string = array.AsStringArray()
// Get the JsonArray as a slice of int
var intArray []int = array.AsIntArray()
// Get the JsonArray as a slice of float
var floatArray []float64 = array.AsFloatArray()
// Get the JsonArray as a slice of JsonArray
var nestedArray []JsonArray = array.As2DArray()
// Get the JsonArray as a slice of JsonObject
var objectArray []JsonObject = array.AsObjectArray()If the array contains null values, and you want to represent that as nil value instead of zero value, you can
use one of the following functions that returns a pointer rather than a value which allows nil. This set of methods
do not set the LastError when a null value was found but instead returns it without reporting an error.
Note! This applies only for the scalar types. JsonObject and JsonArray will return an instance anyway,
and you should use the IsNull() method to check if they are null.
// Get the JsonArray as a slice of nullable strings
var nullableStringArray []*string = array.AsStringArrayN()
// Get the JsonArray as a slice of nullable ints
var nullableIntArray []*int = array.AsIntArrayN()
// Get the JsonArray as a slice of nullable floats
var nullableSloatArray []*float64 = array.AsFloatArrayN()To get a string value as time.Time
var birthday time.Time = object.GetTime("birthday") // 1981-10-08T00:00:00Z
var birthday time.Time = array.GetTime(0)
var birthday time.Time = mapper.AsTime()The mapper will try to format the string against different time formats to increase the chance of correct parsing. The following formats are supported:
time.RFC3339 time.RFC850 time.RFC822 time.RFC822Z time.RFC1123 time.RFC1123Z time.RFC3339Nano time.ANSIC time.UnixDate time.RubyDate time.Layout time.Kitchen time.Stamp time.StampMilli time.StampMicro time.StampNano time.DateTime time.DateOnly time.TimeOnly
You can also get a string value as uuid.UUID type
var uuidValue uuid.UUID = object.GetUUID("id")
var uuidValue uuid.UUID = array.GetUUID(0)
var uuidValue uuid.UUID = mapper.AsUUID()To check what type is your JsonMapper currently holding, use
fmt.Println(mapper.IsObject) // true
fmt.Println(mapper.IsBool) // false
fmt.Println(mapper.IsInt) // false
fmt.Println(mapper.IsFloat) // false
fmt.Println(mapper.IsString) // false
fmt.Println(mapper.IsArray) // false
fmt.Println(mapper.IsNull) // falseEvery JSON element - JsonObject, JsonArray or JsonMapper - have the method String() and PrettyString().
The returned string from these methods will be a valid JSON. For example
fmt.Println(mapper.AsObject.String())
// output: {"age":43,"children":{"Rachel":{"age":15,"is_funny":false},"Sara":{"age":19,"is_funny":true}},"features":["tall","blue eyes"],"is_funny":false,"name":"Jason"}
fmt.Println(mapper.AsObject.Get("children").String())
// output: {"Rachel":{"age":15,"is_funny":false},"Sara":{"age":19,"is_funny":true}}or with PrettyString()
fmt.Println(object.GetObject("children").PrettyString())
// output:
// {
// "address": null,
// "age": 43,
// "birthday": "1981-10-08",
// "children": {
// "Rachel": {
// "age": 15,
// "is_funny": false
// },
// "Sara": {
// "age": 19,
// "is_funny": true
// }
// },
// "features": [
// "tall",
// "blue eyes",
// null
// ],
// "height": 1.87,
// "is_funny": false,
// "name": "Jason"
// }To write a JSON object or array is as simple as reading from it.
// Create a new object
obj := jogson.NewObject()
obj.AddKeyValue("name", "Chris")
fmt.Println(obj.String()) // {"name":"Chris"}// Create a new array
arr := jogson.NewArray()
arr.AddElement(15)
arr.AddElement(19)
fmt.Println(arr.String()) // [15,19]Error handling is designed in such a way to not break the flow and to allow a cleaner code. In most cases
errors are not returned, but instead, they are stored in an exported field, LastError, which can be found in
both JsonObject and JsonArray and can be used to check for the type of error after an operation is made.
_ = object.GetString("non-existent-key")
if object.LastError != nil {
fmt.Println(object.LastError) // output: key was not found: 'non-existent-key'
}Note, LastError is reset at the beginning of every operation, so if you need a reference to an old
error, you will have to store it in a variable. For example:
_ = object.GetString("address")
fmt.Println(object.LastError) // output: type conversion error: <nil> could not be converted to string
_ = object.GetString("name")
fmt.Println(object.LastError) // output: <nil>There are 3 structs that are important to know when working with the library
JsonMapperstruct for generic JSON.JsonObjectrepresents JSON object.JsonArrayrepresents JSON array.
JsonMapper is a struct that holds JSON data and serves as a generic type for all possible JSON types. It has AsX and IsX
fields with which you can get the data and check the type, respectively. For example, if your data is a JSON object,
you can call JsonMapper.AsObject, or if it's a string, JsonMapper.AsString. This struct is best used when you don't
know the type at compile time and want to check it dynamically. In this case you can use JsonMapper.IsArray,
JsonMapper.IsString, JsonMapper.IsFloat, etc.
Note, in any case, AsX never returns nil, but always the zero value. If the underlying data is null, then IsNull will
be set to true.
JsonMapper is also returned in cases where the return type can be any JSON type. For example, JsonArray.Elements()
returns a slice []JsonMapper over which you can iterate or query specific elements. Other methods that return JsonMapper
(instead of JsonObject or JsonArray) are JsonObject.Values(), JsonObject.Get(), JsonArray.Get(), JsonArray.Find() and more.
JsonObject holds JSON object data and has different methods to read from JSON object and write to it. Once you have an instance,
you can use the various methods to read or write data to you object. There are multiple ways to get a JsonObject. You can parse
it directly, get it as an element of an array, or a value in a parent object.
There are 3 sets of methods that you can use when working with JsonObject.
GetX(key string): gets a value in the object as the requested type. For example, GetString("key") gets the value associated withkeyas typestringAsXMap(): gets the value as the requested type. For example, AsStringMap("key") gets the value associated withkeyas typemap[string]stringAddX(key string, value X): addsvalue, associated withkey, to the object as the requested type. For example,AddString("key", "string_value")adds the stringstring_valueassociated with thekey
JsonArray is in many ways almost identical to JsonObject. It also contains the underlying array and methods to read and
write data, and both also keep the same names for the methods. However, they have some minor differences. You can read more about them
in the next section.
The structs JsonObject and JsonArray have very similar methods, both in naming and semantics. For example, both structs
have GetString(), GetInt(), GetFloat(), IsNull(), IsEmpty() and other methods that are identical in names. Additionally,
they both have similar method names with the similar semantics. For example, JsonObject.AsStringMap will return map[string]string,
whereas JsonArray.AsStringArray will return []string.
As a rule of thumb, they have 2 differences:
- Input:
JsonObject's methods mostly take astringas the key, e.g.GetInt("age").JsonArray's methods mostly take anintas the index, e.g.GetBool(1).
- Output:
JsonObject's methods mostly return amaporJsonObject, e.g.GetFloatMap() -> map[string]string.JsonArray's methods mostly return asliceorJsonArray, e.g.GetFloatArray(1) -> []float.
The prefixes, As, Is, Get and Add have similar semantics across the library and can be found in JsonMapper, JsonObject
and JsonArray.
IsX: checks for the value's type. For exampleJsonMapper.IsBoolAsX: converts the current data to other type representation. For example,JsonArray.AsStringArray()converts JsonArray to[]string.GetX: Fetches the data, usually with some sort of search in the underlying data.AddX: Adds the data to the JSON array or object