valyala / fastjson

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

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to construct nested JSON using for loops and arenapools?

clarencefoy opened this issue · comments

Hi, I am currently having to construct a JSON file containing three things. Instances, versions and function names.

Each instance has a version, each version has multiple function names.

Therefore, each 'version' is an array. Each 'instance' has multiple versions.

In pseudocode, I would append each 'function name' to an array (which will be 'version'), and then I would set a key within 'instance' to the 'version', which holds this array of 'function name'.

The problem is that I can't for the life of me figure out how to use the ArenaPool approach to make this safe. It would appear I am always ending up with the 'version' array containing the entries of the last for loop that has been iterated through.

See the following code:


	instances := []Stat{}
	versions := []Stat{}
	functions := []Stat{}
	var ap fastjson.ArenaPool
	are := ap.Get()
	verJSON := are.NewObject()
	instJSON := are.NewObject()

	err := sts.db.Select(&instances, "select distinct on (instance) instance from stats")
	if err != nil {
		[handle error]
		return nil, err
	}


	for _, inst := range instances {
		err := sts.db.Select(&versions, "select distinct on (version) version from stats WHERE instance = $1", inst.Instance)
		if err != nil {
			[handle error]
			return nil, err
		}
		for _, ver := range versions {
			err := sts.db.Select(&functions, "select distinct on (func_name) func_name from stats where instance = $1 and version = $2", inst.Instance, ver.Version)
			if err != nil {
				[handle error]
				return nil, err
			}
			newAr := ap.Get()
			defer ap.Put(newAr)
			arr := newAr.NewArray()
			for i, fun := range functions {
				arr.SetArrayItem(i, newAr.NewString(fun.FuncName))
			}
			verJSON.Set(ver.Version, arr)
			functions = nil
			instJSON.Set(inst.Instance, verJSON)
		}
		versions = nil
	}

	fmt.Println("This is instJSON: ", instJSON)

'instJSON' always ends up containing the 'verJSON' from the second to last and last loop of 'range instances'.