Skip to main content
Glama
orneryd

M.I.M.I.R - Multi-agent Intelligent Memory & Insight Repository

by orneryd
json.go9.48 kB
// Package json provides APOC JSON functions. // // This package implements all apoc.json.* functions for working with // JSON data in Cypher queries. package json import ( "encoding/json" "strings" ) // Path extracts a value from JSON using a path expression. // // Example: // apoc.json.path('{"user":{"name":"Alice"}}', '$.user.name') => 'Alice' func Path(jsonStr, path string) interface{} { var data interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return nil } return extractPath(data, parsePath(path)) } // Validate validates a JSON string. // // Example: // apoc.json.validate('{"name":"Alice"}') => true // apoc.json.validate('{invalid}') => false func Validate(jsonStr string) bool { var data interface{} return json.Unmarshal([]byte(jsonStr), &data) == nil } // Parse parses a JSON string into a value. // // Example: // apoc.json.parse('{"name":"Alice"}') => {name: 'Alice'} func Parse(jsonStr string) interface{} { var data interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return nil } return data } // Stringify converts a value to JSON string. // // Example: // apoc.json.stringify({name: 'Alice'}) => '{"name":"Alice"}' func Stringify(value interface{}) string { bytes, err := json.Marshal(value) if err != nil { return "" } return string(bytes) } // Pretty formats JSON with indentation. // // Example: // apoc.json.pretty('{"name":"Alice"}') => formatted JSON func Pretty(jsonStr string) string { var data interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return jsonStr } bytes, err := json.MarshalIndent(data, "", " ") if err != nil { return jsonStr } return string(bytes) } // Compact removes whitespace from JSON. // // Example: // apoc.json.compact('{\n "name": "Alice"\n}') => '{"name":"Alice"}' func Compact(jsonStr string) string { var data interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return jsonStr } bytes, err := json.Marshal(data) if err != nil { return jsonStr } return string(bytes) } // Keys returns all keys from a JSON object. // // Example: // apoc.json.keys('{"name":"Alice","age":30}') => ['name', 'age'] func Keys(jsonStr string) []string { var data map[string]interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return []string{} } keys := make([]string, 0, len(data)) for k := range data { keys = append(keys, k) } return keys } // Values returns all values from a JSON object. // // Example: // apoc.json.values('{"name":"Alice","age":30}') => ['Alice', 30] func Values(jsonStr string) []interface{} { var data map[string]interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return []interface{}{} } values := make([]interface{}, 0, len(data)) for _, v := range data { values = append(values, v) } return values } // Type returns the type of a JSON value. // // Example: // apoc.json.type('{"name":"Alice"}') => 'object' // apoc.json.type('[1,2,3]') => 'array' func Type(jsonStr string) string { var data interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return "invalid" } switch data.(type) { case map[string]interface{}: return "object" case []interface{}: return "array" case string: return "string" case float64: return "number" case bool: return "boolean" case nil: return "null" default: return "unknown" } } // Size returns the size of a JSON structure. // // Example: // apoc.json.size('{"name":"Alice","age":30}') => 2 // apoc.json.size('[1,2,3,4,5]') => 5 func Size(jsonStr string) int { var data interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return 0 } switch v := data.(type) { case map[string]interface{}: return len(v) case []interface{}: return len(v) default: return 0 } } // Merge merges multiple JSON objects. // // Example: // apoc.json.merge('{"a":1}', '{"b":2}') => '{"a":1,"b":2}' func Merge(jsonStrs ...string) string { result := make(map[string]interface{}) for _, jsonStr := range jsonStrs { var data map[string]interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { continue } for k, v := range data { result[k] = v } } bytes, _ := json.Marshal(result) return string(bytes) } // Set sets a value in JSON at a path. // // Example: // apoc.json.set('{"user":{}}', '$.user.name', 'Alice') // => '{"user":{"name":"Alice"}}' func Set(jsonStr, path string, value interface{}) string { var data interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return jsonStr } setPath(data, parsePath(path), value) bytes, _ := json.Marshal(data) return string(bytes) } // Delete removes a value from JSON at a path. // // Example: // apoc.json.delete('{"name":"Alice","age":30}', '$.age') // => '{"name":"Alice"}' func Delete(jsonStr, path string) string { var data interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return jsonStr } deletePath(data, parsePath(path)) bytes, _ := json.Marshal(data) return string(bytes) } // Flatten flattens a nested JSON structure. // // Example: // apoc.json.flatten('{"user":{"name":"Alice"}}') // => '{"user.name":"Alice"}' func Flatten(jsonStr string) string { var data interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return jsonStr } flattened := make(map[string]interface{}) flattenHelper(data, "", flattened) bytes, _ := json.Marshal(flattened) return string(bytes) } // Unflatten unflattens a flat JSON structure. // // Example: // apoc.json.unflatten('{"user.name":"Alice"}') // => '{"user":{"name":"Alice"}}' func Unflatten(jsonStr string) string { var data map[string]interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return jsonStr } unflattened := make(map[string]interface{}) for key, value := range data { parts := strings.Split(key, ".") current := unflattened for i := 0; i < len(parts)-1; i++ { if _, ok := current[parts[i]]; !ok { current[parts[i]] = make(map[string]interface{}) } current = current[parts[i]].(map[string]interface{}) } current[parts[len(parts)-1]] = value } bytes, _ := json.Marshal(unflattened) return string(bytes) } // Filter filters a JSON array based on a predicate. // // Example: // apoc.json.filter('[1,2,3,4,5]', 'x > 3') => '[4,5]' func Filter(jsonStr string, predicate func(interface{}) bool) string { var data []interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return jsonStr } filtered := make([]interface{}, 0) for _, item := range data { if predicate(item) { filtered = append(filtered, item) } } bytes, _ := json.Marshal(filtered) return string(bytes) } // Map transforms a JSON array. // // Example: // apoc.json.map('[1,2,3]', 'x * 2') => '[2,4,6]' func Map(jsonStr string, transform func(interface{}) interface{}) string { var data []interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return jsonStr } mapped := make([]interface{}, len(data)) for i, item := range data { mapped[i] = transform(item) } bytes, _ := json.Marshal(mapped) return string(bytes) } // Reduce reduces a JSON array to a single value. // // Example: // apoc.json.reduce('[1,2,3,4,5]', 0, 'acc + x') => 15 func Reduce(jsonStr string, initial interface{}, reducer func(interface{}, interface{}) interface{}) interface{} { var data []interface{} if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { return initial } result := initial for _, item := range data { result = reducer(result, item) } return result } // Helper functions func parsePath(path string) []string { // Simple path parser for $.a.b.c format path = strings.TrimPrefix(path, "$.") path = strings.TrimPrefix(path, "$") if path == "" { return []string{} } return strings.Split(path, ".") } func extractPath(data interface{}, path []string) interface{} { if len(path) == 0 { return data } switch v := data.(type) { case map[string]interface{}: if val, ok := v[path[0]]; ok { return extractPath(val, path[1:]) } case []interface{}: // Handle array index // Simplified - in production, parse index from path if len(v) > 0 { return extractPath(v[0], path[1:]) } } return nil } func setPath(data interface{}, path []string, value interface{}) { if len(path) == 0 { return } if m, ok := data.(map[string]interface{}); ok { if len(path) == 1 { m[path[0]] = value } else { if _, ok := m[path[0]]; !ok { m[path[0]] = make(map[string]interface{}) } setPath(m[path[0]], path[1:], value) } } } func deletePath(data interface{}, path []string) { if len(path) == 0 { return } if m, ok := data.(map[string]interface{}); ok { if len(path) == 1 { delete(m, path[0]) } else { if nested, ok := m[path[0]]; ok { deletePath(nested, path[1:]) } } } } func flattenHelper(data interface{}, prefix string, result map[string]interface{}) { switch v := data.(type) { case map[string]interface{}: for key, value := range v { newKey := key if prefix != "" { newKey = prefix + "." + key } if nested, ok := value.(map[string]interface{}); ok { flattenHelper(nested, newKey, result) } else { result[newKey] = value } } default: result[prefix] = data } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/orneryd/Mimir'

If you have feedback or need assistance with the MCP directory API, please join our Discord server