package api import ( "encoding/json" "fmt" ) // ChainedVars holds auto-extracted fields from the most-recent response. // Keys are formatted as "last_FIELD" (top-level) or "last_PARENT_FIELD" // (one level of nesting). Use them in any request as {{last_id}}, etc. // // The map is replaced entirely on each successful response so stale values // from a previous call do not bleed into unrelated requests. var ChainedVars = make(map[string]string) // ExtractChained parses body as a JSON object and populates ChainedVars. // Non-JSON bodies are silently ignored. func ExtractChained(body []byte) { var data map[string]interface{} if err := json.Unmarshal(body, &data); err != nil { return } next := make(map[string]string) flattenJSON(next, "last", data, 0) ChainedVars = next } // flattenJSON recursively walks obj up to maxDepth levels deep. func flattenJSON(dst map[string]string, prefix string, obj map[string]interface{}, depth int) { if depth > 1 { return } for k, v := range obj { key := prefix + "_" + k switch val := v.(type) { case string: dst[key] = val case float64: if val == float64(int64(val)) { dst[key] = fmt.Sprintf("%d", int64(val)) } else { dst[key] = fmt.Sprintf("%g", val) } case bool: if val { dst[key] = "true" } else { dst[key] = "false" } case map[string]interface{}: flattenJSON(dst, key, val, depth+1) } } }