624 lines
13 KiB
Go
624 lines
13 KiB
Go
package jaeson
|
|
|
|
import (
|
|
"errors"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
JSON_VAL_TYPE_STRING = "str"
|
|
JSON_VAL_TYPE_INT = "int"
|
|
JSON_VAL_TYPE_FLOAT = "float"
|
|
JSON_VAL_TYPE_BOOL = "jsbln"
|
|
JSON_VAL_TYPE_OBJECT = "jsobj"
|
|
JSON_VAL_TYPE_ARRAY = "jsarr"
|
|
)
|
|
|
|
type JSONObject struct {
|
|
|
|
ms map[string]string
|
|
mo map[string]*JSONObject
|
|
marr map[string]*JSONArray
|
|
mn map[string]int
|
|
mbln map[string]bool
|
|
mflt64 map[string]float64
|
|
|
|
//contains all valid keys
|
|
mAllkeys map[string]string
|
|
|
|
ctms int
|
|
ctmo int
|
|
ctmarr int
|
|
ctmn int
|
|
ctmbln int
|
|
ctmflt64 int
|
|
|
|
hasVal bool
|
|
//isSorted bool
|
|
}
|
|
|
|
func NewJSONObject() *JSONObject {
|
|
jsObj := new(JSONObject)
|
|
jsObj.Init()
|
|
return jsObj
|
|
}
|
|
func NewJSONArray() *JSONArray {
|
|
jsArr := new(JSONArray)
|
|
jsArr.Init()
|
|
return jsArr
|
|
}
|
|
|
|
func (v *JSONObject) Init() {
|
|
v.ctms = 0
|
|
v.ctmo = 0
|
|
v.ctmarr = 0
|
|
v.ctmn = 0
|
|
v.ctmbln = 0
|
|
v.ctmflt64 = 0
|
|
|
|
v.ms = make(map[string]string, 0)
|
|
v.mo = make(map[string]*JSONObject, 0)
|
|
v.marr = make(map[string]*JSONArray, 0)
|
|
v.mn = make(map[string]int, 0)
|
|
v.mbln = make(map[string]bool, 0)
|
|
v.mflt64 = make(map[string]float64, 0)
|
|
|
|
v.hasVal = false
|
|
//v.isSorted = false
|
|
|
|
v.mAllkeys = make(map[string]string, 0)
|
|
|
|
}
|
|
|
|
func (v *JSONObject) KeySetSize() int {
|
|
return v.ctms + v.ctmo + v.ctmarr + v.ctmn + v.ctmbln
|
|
}
|
|
|
|
func (v *JSONObject) Map() map[string]string {
|
|
return v.mAllkeys
|
|
}
|
|
|
|
//---------- PUT ----------//
|
|
|
|
func (v *JSONObject) PutString(key string, value string) {
|
|
if v.mAllkeys[key] == JSON_VAL_TYPE_OBJECT {
|
|
v.RemoveJSONObject(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_ARRAY {
|
|
v.RemoveJSONArray(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_INT {
|
|
v.RemoveInt(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_BOOL {
|
|
v.RemoveBool(key)
|
|
}
|
|
v.ms[key] = value
|
|
v.ctms += 1
|
|
v.hasVal = true
|
|
|
|
v.mAllkeys[key] = JSON_VAL_TYPE_STRING
|
|
}
|
|
|
|
func (v *JSONObject) PutJSONObject(key string, value *JSONObject) {
|
|
if v.mAllkeys[key] == JSON_VAL_TYPE_ARRAY {
|
|
v.RemoveJSONArray(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_INT {
|
|
v.RemoveInt(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_STRING {
|
|
v.RemoveString(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_BOOL {
|
|
v.RemoveBool(key)
|
|
}
|
|
v.mo[key] = value
|
|
v.ctmo += 1
|
|
v.hasVal = true
|
|
|
|
v.mAllkeys[key] = JSON_VAL_TYPE_OBJECT
|
|
}
|
|
|
|
func (v *JSONObject) PutJSONArray(key string, value *JSONArray) {
|
|
if v.mAllkeys[key] == JSON_VAL_TYPE_OBJECT {
|
|
v.RemoveJSONObject(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_INT {
|
|
v.RemoveInt(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_STRING {
|
|
v.RemoveString(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_BOOL {
|
|
v.RemoveBool(key)
|
|
}
|
|
v.marr[key] = value
|
|
v.ctmarr += 1
|
|
v.hasVal = true
|
|
|
|
v.mAllkeys[key] = JSON_VAL_TYPE_ARRAY
|
|
}
|
|
|
|
func (v *JSONObject) PutInt(key string, value int) {
|
|
if v.mAllkeys[key] == JSON_VAL_TYPE_OBJECT {
|
|
v.RemoveJSONObject(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_ARRAY {
|
|
v.RemoveJSONArray(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_STRING {
|
|
v.RemoveString(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_BOOL {
|
|
v.RemoveBool(key)
|
|
}
|
|
v.mn[key] = value
|
|
v.ctmn += 1
|
|
v.hasVal = true
|
|
|
|
v.mAllkeys[key] = JSON_VAL_TYPE_INT
|
|
}
|
|
|
|
func (v *JSONObject) PutNumber(key string, value int) {
|
|
v.PutInt(key, value)
|
|
}
|
|
|
|
func (v *JSONObject) PutBool(key string, value bool) {
|
|
if v.mAllkeys[key] == JSON_VAL_TYPE_OBJECT {
|
|
v.RemoveJSONObject(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_ARRAY {
|
|
v.RemoveJSONArray(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_STRING {
|
|
v.RemoveString(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_INT {
|
|
v.RemoveInt(key)
|
|
}
|
|
v.mbln[key] = value
|
|
v.ctmbln += 1
|
|
v.hasVal = true
|
|
|
|
v.mAllkeys[key] = JSON_VAL_TYPE_BOOL
|
|
}
|
|
|
|
func (v *JSONObject) PutFloat(key string, value float64) {
|
|
|
|
if v.mAllkeys[key] == JSON_VAL_TYPE_OBJECT {
|
|
v.RemoveJSONObject(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_ARRAY {
|
|
v.RemoveJSONArray(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_STRING {
|
|
v.RemoveString(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_INT {
|
|
v.RemoveInt(key)
|
|
} else if v.mAllkeys[key] == JSON_VAL_TYPE_BOOL {
|
|
v.RemoveBool(key)
|
|
}
|
|
v.mflt64[key] = value
|
|
v.ctmflt64 += 1
|
|
v.hasVal = true
|
|
|
|
v.mAllkeys[key] = JSON_VAL_TYPE_FLOAT
|
|
}
|
|
|
|
//---------- ACCUMULATE ----------//
|
|
func (v *JSONObject) AccumulateJSONObject(key string, value *JSONObject) {
|
|
|
|
jsArr, err := v.GetJSONArray(key)
|
|
if err != nil {
|
|
v.RemoveString(key)
|
|
v.RemoveJSONObject(key)
|
|
|
|
jsArr := NewJSONArray()
|
|
jsArr.AddJSONObject(value)
|
|
|
|
v.PutJSONArray(key, jsArr)
|
|
|
|
} else {
|
|
|
|
jsArr.AddJSONObject(value)
|
|
}
|
|
}
|
|
|
|
//---------- GET ----------//
|
|
func (v *JSONObject) GethasVal() bool {
|
|
return v.hasVal
|
|
}
|
|
|
|
func (v *JSONObject) GetString(key string) (string, error) {
|
|
if v.ctms > 0 {
|
|
val, isContainsKey := v.ms[key]
|
|
if isContainsKey {
|
|
return val, nil
|
|
}else{
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return "", err
|
|
} else {
|
|
return "", errors.New("value not a string")
|
|
}
|
|
}
|
|
} else {
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return "", err
|
|
} else {
|
|
return "", errors.New("value not an string")
|
|
}
|
|
}
|
|
}
|
|
|
|
func (v *JSONObject) GetJSONObject(key string) (*JSONObject, error) {
|
|
if v.ctmo > 0 {
|
|
val, isContainsKey := v.mo[key]
|
|
if isContainsKey {
|
|
return val, nil
|
|
}else{
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return nil, err
|
|
} else {
|
|
return nil, errors.New("value not a JSONObject")
|
|
}
|
|
}
|
|
} else {
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return nil, err
|
|
} else {
|
|
return nil, errors.New("value not an JSONObject")
|
|
}
|
|
}
|
|
}
|
|
|
|
func (v *JSONObject) GetJSONArray(key string) (*JSONArray, error) {
|
|
if v.ctmarr > 0 {
|
|
val, isContainsKey := v.marr[key]
|
|
if isContainsKey {
|
|
return val, nil
|
|
}else{
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return nil, err
|
|
} else {
|
|
return nil, errors.New("value not a JSONArray")
|
|
}
|
|
}
|
|
} else {
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return nil, err
|
|
} else {
|
|
return nil, errors.New("value not an JSONArray")
|
|
}
|
|
}
|
|
}
|
|
|
|
func (v *JSONObject) GetInt(key string) (int, error) {
|
|
if v.ctmn > 0 {
|
|
val, isContainsKey := v.mn[key]
|
|
if isContainsKey {
|
|
return val, nil
|
|
|
|
}else{
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return -1, err
|
|
} else {
|
|
return -1, errors.New("value not an int")
|
|
}
|
|
}
|
|
} else {
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return -1, err
|
|
} else {
|
|
return -1, errors.New("value not an int")
|
|
}
|
|
}
|
|
}
|
|
|
|
func (v *JSONObject) GetNumber(key string) (int, error) {
|
|
return v.GetInt(key)
|
|
}
|
|
|
|
func (v *JSONObject) GetBool(key string) (bool, error) {
|
|
if v.ctmbln > 0 {
|
|
val, isContainsKey := v.mbln[key]
|
|
if isContainsKey {
|
|
return val, nil
|
|
}else{
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return false, err
|
|
} else {
|
|
return false, errors.New("value not a bool")
|
|
}
|
|
}
|
|
} else {
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return false, err
|
|
} else {
|
|
return false, errors.New("value not a bool")
|
|
}
|
|
}
|
|
}
|
|
|
|
func (v *JSONObject) GetFloat(key string) (float64, error) {
|
|
if v.ctmflt64 > 0 {
|
|
val, isContainsKey := v.mflt64[key]
|
|
if isContainsKey {
|
|
return val, nil
|
|
}else{
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return -1, err
|
|
} else {
|
|
return -1, errors.New("value not a float")
|
|
}
|
|
}
|
|
} else {
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return -1, err
|
|
} else {
|
|
return -1, errors.New("value not a float")
|
|
}
|
|
}
|
|
}
|
|
|
|
func (v *JSONObject) GetValType(key string) (string, error) {
|
|
|
|
if len(v.mAllkeys) > 0 {
|
|
valType := v.mAllkeys[key]
|
|
if len(valType) == 0 {
|
|
return "", errors.New("key not found")
|
|
} else {
|
|
return valType, nil
|
|
}
|
|
} else {
|
|
return "", errors.New("key not found")
|
|
}
|
|
}
|
|
|
|
//---------- func REMOVE ----------//
|
|
func (v *JSONObject) RemoveString(key string) (error) {
|
|
if v.ctms > 0 {
|
|
_, isContainsKey := v.ms[key]
|
|
if isContainsKey {
|
|
delete(v.ms, key)
|
|
delete(v.mAllkeys, key)
|
|
v.ctms = len(v.ms)
|
|
|
|
}else{
|
|
return v.genericRemove(key, "string")
|
|
}
|
|
} else {
|
|
return v.genericRemove(key, "string")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (v *JSONObject) RemoveJSONObject(key string) (error) {
|
|
if v.ctmo > 0 {
|
|
_, isContainsKey := v.mo[key]
|
|
if isContainsKey {
|
|
delete(v.mo, key)
|
|
delete(v.mAllkeys, key)
|
|
v.ctmo = len(v.mo)
|
|
|
|
}else{
|
|
return v.genericRemove(key, "JSONObject")
|
|
}
|
|
} else {
|
|
return v.genericRemove(key, "JSONObject")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (v *JSONObject) RemoveJSONArray(key string) (error) {
|
|
if v.ctmarr > 0 {
|
|
_, isContainsKey := v.marr[key]
|
|
if isContainsKey {
|
|
delete(v.marr, key)
|
|
delete(v.mAllkeys, key)
|
|
v.ctmarr = len(v.marr)
|
|
|
|
}else{
|
|
return v.genericRemove(key, "JSONArray")
|
|
}
|
|
} else {
|
|
return v.genericRemove(key, "JSONArray")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (v *JSONObject) RemoveInt(key string) (error){
|
|
if v.ctmn > 0 {
|
|
_, isContainsKey := v.mn[key]
|
|
if isContainsKey {
|
|
delete(v.mn, key)
|
|
delete(v.mAllkeys, key)
|
|
v.ctmn = len(v.mn)
|
|
|
|
}else{
|
|
return v.genericRemove(key, "int")
|
|
}
|
|
} else {
|
|
return v.genericRemove(key, "int")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (v *JSONObject) RemoveBool(key string) (error){
|
|
if v.ctmbln > 0 {
|
|
_, isContainsKey := v.mbln[key]
|
|
if isContainsKey {
|
|
delete(v.mbln, key)
|
|
delete(v.mAllkeys, key)
|
|
v.ctmbln = len(v.mbln)
|
|
|
|
}else{
|
|
return v.genericRemove(key, "bool")
|
|
}
|
|
} else {
|
|
return v.genericRemove(key, "bool")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (v *JSONObject) RemoveFloat(key string) (error){
|
|
if v.ctmflt64 > 0 {
|
|
_, isContainsKey := v.mflt64[key]
|
|
if isContainsKey {
|
|
delete(v.mflt64, key)
|
|
delete(v.mAllkeys, key)
|
|
v.ctmflt64 = len(v.mflt64)
|
|
|
|
}else{
|
|
return v.genericRemove(key, "float")
|
|
}
|
|
} else {
|
|
return v.genericRemove(key, "float")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (v *JSONObject) RemoveAny(key string) (error){
|
|
_, isContainsKey := v.mAllkeys[key]
|
|
if isContainsKey {
|
|
valType, err := v.GetValType(key)
|
|
if err != nil {
|
|
return err
|
|
} else {
|
|
// delete appropriate collection
|
|
switch valType {
|
|
case JSON_VAL_TYPE_STRING:
|
|
delete(v.ms, key)
|
|
delete(v.mAllkeys, key)
|
|
v.ctms = len(v.ms)
|
|
case JSON_VAL_TYPE_BOOL:
|
|
delete(v.mbln, key)
|
|
delete(v.mAllkeys, key)
|
|
v.ctmbln = len(v.mbln)
|
|
case JSON_VAL_TYPE_INT:
|
|
delete(v.mn, key)
|
|
delete(v.mAllkeys, key)
|
|
v.ctmn = len(v.mn)
|
|
case JSON_VAL_TYPE_FLOAT:
|
|
delete(v.mflt64, key)
|
|
delete(v.mAllkeys, key)
|
|
v.ctmflt64 = len(v.mflt64)
|
|
case JSON_VAL_TYPE_OBJECT:
|
|
delete(v.mo, key)
|
|
delete(v.mAllkeys, key)
|
|
v.ctmo = len(v.mo)
|
|
case JSON_VAL_TYPE_ARRAY:
|
|
delete(v.marr, key)
|
|
delete(v.mAllkeys, key)
|
|
v.ctmarr = len(v.marr)
|
|
default:
|
|
return errors.New("Invalid date type: " + valType)
|
|
}
|
|
}
|
|
}else{
|
|
return errors.New("key not found")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (v *JSONObject) genericRemove(key string, msgSuffx string) (error){
|
|
_, err := v.GetValType(key)
|
|
if err != nil {
|
|
return err
|
|
} else {
|
|
return errors.New("value not a "+msgSuffx)
|
|
}
|
|
}
|
|
|
|
//---------- PRINT STRING----------//
|
|
func (v *JSONObject) String() string {
|
|
|
|
var out string = "{"
|
|
|
|
if v.ctms > 0 {
|
|
for keyms, _ := range v.ms {
|
|
out += "\"" + keyms + "\":\"" + v.ms[keyms] + "\","
|
|
}
|
|
}
|
|
|
|
if v.ctmn > 0 {
|
|
for keymn, _ := range v.mn {
|
|
out += "\"" + keymn + "\":" + strconv.Itoa(v.mn[keymn]) + ","
|
|
}
|
|
}
|
|
|
|
if v.ctmo > 0 {
|
|
for keymo, _ := range v.mo {
|
|
jsObj := v.mo[keymo]
|
|
out += "\"" + keymo + "\":" + jsObj.String() + ","
|
|
}
|
|
}
|
|
|
|
if v.ctmarr > 0 {
|
|
for keymarr, _ := range v.marr {
|
|
jsArr := v.marr[keymarr]
|
|
out += "\"" + keymarr + "\":" + jsArr.String() + ","
|
|
}
|
|
}
|
|
|
|
if v.ctmbln > 0 {
|
|
for keymbln, _ := range v.mbln {
|
|
if v.mbln[keymbln] {
|
|
out += "\"" + keymbln + "\":true,"
|
|
}else{
|
|
out += "\"" + keymbln + "\":false,"
|
|
}
|
|
}
|
|
}
|
|
|
|
if v.ctmflt64 > 0 {
|
|
for keymflt64, _ := range v.mflt64 {
|
|
out += "\"" + keymflt64 + "\":" + strconv.FormatFloat(v.mflt64[keymflt64], 'f', -1, 64 ) + ","
|
|
}
|
|
}
|
|
|
|
if strings.HasSuffix(out, ",") {
|
|
out = out[0 : len(out)-1]
|
|
}
|
|
out += "}"
|
|
return out
|
|
}
|
|
|
|
func (v *JSONObject) StringJCS() string {
|
|
|
|
var out string = "{"
|
|
var keys []string
|
|
|
|
keys = make([]string, 0, len(v.mAllkeys))
|
|
for k := range v.mAllkeys {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
|
|
iLenKeys := len(keys)
|
|
for idx := 0; idx < iLenKeys; idx++ {
|
|
key := keys[idx]
|
|
tmpVal := v.mAllkeys[key]
|
|
|
|
switch tmpVal {
|
|
case JSON_VAL_TYPE_OBJECT:
|
|
jsObj := v.mo[key]
|
|
out += "\"" + key + "\":\"" + jsObj.StringJCS() + "\","
|
|
case JSON_VAL_TYPE_ARRAY:
|
|
jsArr := v.marr[key]
|
|
out += "\"" + key + "\":" + jsArr.String() + ","
|
|
case JSON_VAL_TYPE_BOOL:
|
|
out += "\"" + key + "\":" + strconv.FormatBool(v.mbln[key]) + ","
|
|
case JSON_VAL_TYPE_INT:
|
|
out += "\"" + key + "\":" + strconv.Itoa(v.mn[key]) + ","
|
|
case JSON_VAL_TYPE_FLOAT:
|
|
out += "\"" + key + "\":" + strconv.FormatFloat(v.mflt64[key], 'f', -1, 64 ) + ","
|
|
default:
|
|
out += "\"" + key + "\":\"" + v.ms[key] + "\","
|
|
}
|
|
}
|
|
if strings.HasSuffix(out, ",") {
|
|
out = out[0 : len(out)-1]
|
|
}
|
|
out += "}"
|
|
return out
|
|
}
|