# Nested JSON Manipulation Example

This directory contains an advanced example demonstrating nested JSON object manipulation using the uni-json library.

## Files

- `nested_example.c` - Main example demonstrating complex JSON operations
- `nested_bindings.c` - Enhanced C bindings for uni-json library
- `Makefile` - Build system for the nested example

## Building

```bash
# Build the example
make

# Or build and run
make run

# Clean build files
make clean
```

## Features Demonstrated

### 1. Complex Nested JSON Parsing

The example parses a complex nested JSON structure:

```json
{
  "device": {
    "name": "sensor-001",
    "type": "temperature",
    "metadata": {
      "location": "server-room-1",
      "installed": "2023-01-15",
      "config": {
        "interval": 60,
        "threshold": {
          "min": 18.5,
          "max": 25.0,
          "critical": 30.0
        }
      }
    }
  },
  "system": {
    "version": "1.2.3",
    "uptime": 86400,
    "debug": true
  },
  "network": {
    "interfaces": [
      {
        "name": "eth0",
        "ip": "192.168.1.100",
        "active": true
      },
      {
        "name": "wlan0",
        "ip": "192.168.1.101",
        "active": false
      }
    ]
  }
}
```

### 2. JSON Querying Operations

#### Direct Key Access
```c
struct uni_json_value *device = find_key_in_object(root, "device");
```

#### Nested Path Access
```c
struct uni_json_value *name = find_nested_path(root, "device.name");
struct uni_json_value *version = find_nested_path(root, "system.version");
```

#### Array Element Access
```c
struct uni_json_value *interfaces = find_nested_path(root, "network.interfaces");
```

### 3. JSON Creation and Modification

The example demonstrates how to create new JSON objects programmatically:

```c
// Create object
struct uni_json_value *new_obj = uni_json_nested_bindings.make_object();

// Add string value
struct uni_json_value *name_key = uni_json_nested_bindings.finalize_string(NULL, (uint8_t*)"name", 4);
struct uni_json_value *name_val = uni_json_nested_bindings.finalize_string(NULL, (uint8_t*)"New Device", 10);
uni_json_nested_bindings.add_2_object(name_key, name_val, new_obj);

// Add number value
struct uni_json_value *priority_key = uni_json_nested_bindings.finalize_string(NULL, (uint8_t*)"priority", 8);
struct uni_json_value *priority_val = uni_json_nested_bindings.make_number((uint8_t*)"42", 2, 0);
uni_json_nested_bindings.add_2_object(priority_key, priority_val, new_obj);

// Add boolean value
struct uni_json_value *active_key = uni_json_nested_bindings.finalize_string(NULL, (uint8_t*)"active", 6);
struct uni_json_value *active_val = uni_json_nested_bindings.make_bool(1);
uni_json_nested_bindings.add_2_object(active_key, active_val, new_obj);

// Add array
struct uni_json_value *array = uni_json_nested_bindings.make_array();
// Add elements to array...
uni_json_nested_bindings.add_2_object(tags_key, array, new_obj);
```

### 4. Pretty Printing

The example includes a comprehensive pretty-printing function that handles:

- Nested objects with proper indentation
- Arrays with formatted elements
- All JSON value types (strings, numbers, booleans, null)
- Proper key display with string length handling

## Key Implementation Details

### Key Handling in Objects

Unlike the simple example, this implementation correctly handles that **keys are JSON string objects**, not plain C strings:

```c
// WRONG: This treats keys as plain strings
printf("%s", (char*)entry->key);

// CORRECT: Keys are uni_json_value structures
struct uni_json_value *key_val = (struct uni_json_value*)entry->key;
if (key_val->type == UJ_T_STR) {
    printf("%.*s", (int)key_val->u.s.len, key_val->u.s.s);
}
```

### Path-Based Navigation

The `find_nested_path()` function enables dot-notation access to nested values:

```c
struct uni_json_value *value = find_nested_path(root, "device.metadata.config.interval");
```

### Memory Management

- All objects are properly allocated and freed
- Keys are JSON string objects that must be created using `finalize_string()`
- Arrays support mixed-type elements
- Recursive cleanup prevents memory leaks

## Usage Examples

### Querying Values

```c
// Get device name
struct uni_json_value *name = find_nested_path(root, "device.name");
if (name && name->type == UJ_T_STR) {
    printf("Device: %.*s\n", (int)name->u.s.len, name->u.s.s);
}

// Check if device is active
struct uni_json_value *active = find_nested_path(root, "device.active");
if (active && active->type == UJ_T_BOOL) {
    printf("Active: %s\n", active->u.b ? "yes" : "no");
}
```

### Creating Complex Objects

```c
// Create nested structure
struct uni_json_value *config = uni_json_nested_bindings.make_object();
struct uni_json_value *threshold = uni_json_nested_bindings.make_object();

// Add threshold values
uni_json_nested_bindings.add_2_object(
    uni_json_nested_bindings.finalize_string(NULL, (uint8_t*)"min", 3),
    uni_json_nested_bindings.make_number((uint8_t*)"18.5", 4, 0),
    threshold
);

// Add threshold to config
uni_json_nested_bindings.add_2_object(
    uni_json_nested_bindings.finalize_string(NULL, (uint8_t*)"threshold", 9),
    threshold,
    config
);
```

## Integration with VDev

This example demonstrates patterns useful for VDev:

- **Device Configuration**: Parse nested device configurations
- **Event Processing**: Handle complex device event JSON
- **State Management**: Store and retrieve device state
- **Network Configuration**: Manage network interface settings

## Advanced Features

### Error Handling

```c
struct uni_json_value *value = find_nested_path(root, "nonexistent.path");
if (!value) {
    printf("Path not found\n");
} else if (value->type != expected_type) {
    printf("Wrong type at path\n");
}
```

### Type Checking

```c
switch (value->type) {
    case UJ_T_STR:
        printf("String: %.*s\n", (int)value->u.s.len, value->u.s.s);
        break;
    case UJ_T_NUM:
        printf("Number: %g\n", value->u.num);
        break;
    case UJ_T_BOOL:
        printf("Boolean: %s\n", value->u.b ? "true" : "false");
        break;
    // ... other types
}
```

### Array Manipulation

```c
// Iterate through array elements
struct uni_json_array_entry *entry = array->u.ary.first;
int index = 0;
while (entry) {
    printf("Element %d: ", index++);
    print_json_value(entry->value, 0);
    entry = entry->next;
}
```

## Performance Considerations

- **Path Navigation**: O(n) where n is the depth of nesting
- **Key Lookup**: O(m) where m is the number of object entries
- **Memory Usage**: Proportional to JSON structure size
- **Recursive Operations**: Limited by stack depth for very deep nesting

## Extending the Example

To add new features:

1. **New JSON Types**: Extend the `uni_json_value` union
2. **Custom Queries**: Add specialized lookup functions
3. **Validation**: Add schema validation functions
4. **Serialization**: Implement JSON output functions
5. **Modification**: Add functions to modify existing structures

## Comparison with Simple Example

| Feature | Simple Example | Nested Example |
|---------|----------------|----------------|
| JSON Types | Basic | All types |
| Nesting Support | Limited | Full support |
| Query Methods | Direct keys | Path navigation |
| Object Creation | Basic | Complex structures |
| Memory Management | Simple | Comprehensive |
| Error Handling | Basic | Robust |
| Pretty Printing | Basic | Formatted output |

This nested example provides a complete foundation for advanced JSON manipulation in VDev and similar applications.
