La librería estándar para manejar JSONs en Go, encoding/json
, es bastante completa y cumple su función en la mayoría de los casos. Sus funcionalidades más utilizadas son Marshal
y Unmarshal
, que respectivamente se encargan de convertir una esctructura de Go a su representación en JSON y viceversa.
Existen, sin embargo, situaciones en las que esta librería no es suficiente. Por ejemplo, el caso en que se quieran manejar múltiples tags para una misma estructura. Para entender un poco mejor el problema, veamos un ejemplo:
type Person struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
CurrentAge int `json:"current_age"`
}
La anterior estructura cuenta con tres campos, cada uno con un nombre, un tipo y un tag. Estos tags indican qué nombre tendrá ese mismo campo cuando se represente una instancia de esta estructura en format JSON.
¿Qué pasaría si quisieramos, por ejemplo, soportar tanto campos en snake case como en camel case cuando hacemos conversiones de JSON a struct? La respuesta a este problema es jsoniter.
Jsoniter es capaz de hacer todo lo que hace encoding/json
y más. Es un reemplazo para esta librería, que además de tener más funcionalidades, es más rápida.
Para resolver el anterior problema, podemos ver el siguiente código:
type Person struct {
FirstName string `snake:"first_name" camel:"firstName"`
LastName string `snake:"last_name" camel:"lastName"`
CurrentAge int `snake:"current_age" camel:"currentAge"`
}
func print() {
snakeCaseJSON := jsoniter.Config{TagKey: "snake"}.Froze()
camelCaseJSON := jsoniter.Config{TagKey: "camel"}.Froze()
p := &Person{"Pepito", "Perez", 32}
result, _ := snakeCaseJSON.Marshal(p)
fmt.Println(string(result))
result, _ = camelCaseJSON.Marshal(p)
fmt.Println(string(result))
}
Y su output:
{"first_name":"Pepito","last_name":"Perez","current_age":32}
{"firstName":"Pepito","lastName":"Perez","currentAge":32}
Como podemos ver, es posible definir más de un set de tags para los atributos de nuestra estructura. Usando jsoniter podemos crear diferentes APIs para utilizar los métodos de la librería con la configuración que especifiquemos. En este caso, queremos cambiar el TagKey que se utiliza. De esta manera, es posible definir muchos tags y hacer Marshal
y Unmarshal
de nuestra estructura con el tag que sea necesario.