# json_deref
`json_deref` is a Rust library for resolving internal dependencies in JSON structures. It automatically replaces placeholders (e.g., `{some_dependency}`) in JSON strings with their corresponding values, simplifying the handling of self-referencing or cross-referencing JSON data. The library provides multiple utility functions for resolving JSON either into a `Value` (from `serde_json`) or into user-defined types.
## Key Features
- **Dependency resolution for self-referentional JSON** Automatically resolves JSON placeholders (like `{neighbour_value}`, `{../parent_value}`, e.t.c) to their corresponding values.
- **Dependency resolution for template JSON** Automatically resolves JSON placeholders in template (like `{/object/field}`) to their corresponding values using data source JSON.
- **Absolute Path Expansion**: Converts relative dependency paths into absolute paths.
- **Resolving Embedded Dependencies** Resolves multiple embedded dependencies in text
- **Graceful Fallbacks** If a dependency cannot be resolved, the placeholder will be replaced by its absolute path.
- **No Recursion** Only top-level dependencies are resolved. Nested dependencies in resolved text are not recursively processed. This prevents infinite resolution.
- **Error-Tolerant** The library does not generate errors during resolution. All dependencies are processed in a fail-safe manner. If a dependency cannot be resolved, the library will replace it with its absolute path (e.g., /some/absolute/path) rather than throwing an error.
## Installation
Add `json_deref` to your `Cargo.toml` dependencies:
```toml
[dependencies]
json_deref = "0.2.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
```
## Examples of functionality
- Resolving internal dependencies
```rust
let input = json!({
"string_field": "Static Value",
"number_field": 123,
"boolean_field": true,
"null_field": null,
"absolute_field": "{/string_field}", // Absolute path
"relative_field": "{string_field}", // Sibling reference
"embedded_field": "Embedded: {string_field}", // Embedded dependency
"object_field": {
"parent_field": "{../relative_field}", // Resolves a field from parent object. Note that the dependencies will not be resolved recursively.
"out_of_bounds_field": "{../../boolean_field}" // Also resolves a field from parent object
},
"array_field": [
"Static Value", // Static value
"{../number_field}" // Sibling reference in array
],
"unresolvable_field": "{/nonexistent}" // Unresolvable absolute path
});
let resolved = input.resolve_internal_dependencies();
assert_eq!(resolved, json!({
"string_field": "Static Value", // Original value preserved
"number_field": 123, // Original value preserved
"boolean_field": true, // Original boolean preserved
"null_field": null, // Null value preserved
"absolute_field": "Static Value", // Resolved using absolute path
"relative_field": "Static Value", // Resolved sibling reference
"embedded_field": "Embedded: Static Value", // Embedded dependency resolved
"object_field": {
"parent_field": "{/string_field}", // Resolves a field from parent object. Note that the dependencies will not be resolved recursively.
"out_of_bounds_field": true // Also resolves a field from parent object
},
"array_field": [
"Static Value", // Static value unchanged
123 // Resolved sibling reference
],
"unresolvable_field": "{/nonexistent}" // Unresolved dependency remains unchanged
}));
```
- Resolving dependencies using both template and data source JSON
```rust
let template = json!({
"string_field": "{/data/string}",
"number_field": "{/data/number}",
"boolean_field": "{/data/boolean}",
"array_field": "{/data/array}",
"object_field": "{/data/object}",
"null_field": "{/data/null}",
"embedded_field": "Referenced: {/data/string}", // Embedded dependency
"unresolvable_field": "{/data/nonexistent}" // Unresolvable path
});
let source = json!({
"data": {
"string": "String Value",
"number": 123,
"boolean": false,
"array": ["a", "b", "c"],
"object": {"key": "value"},
"null": null
}
});
let resolved = template.resolve_template_with_source(&source);
assert_eq!(resolved, json!({
"string_field": "String Value",
"number_field": 123,
"boolean_field": false,
"array_field": ["a", "b", "c"],
"object_field": {"key": "value"},
"null_field": null,
"embedded_field": "Referenced: String Value",
"unresolvable_field": "{/data/nonexistent}" // Paths not found in source remain unchanged
}));
```
See additional examples in '/examples' dir
## How It Works
json_deref uses the following steps to resolve a JSON structure:
### Path Mapping
A map of dependencies is created by scanning the JSON strings for placeholders like {key} or {path/to/key}.
### Path Conversion
Relative paths are converted to absolute paths for easier reference resolution.
### Dependency Extraction
For each absolute path, the corresponding value in the JSON is extracted.
### Resolution
Placeholders in the JSON are replaced with their resolved values.
## Contributing
If you'd like to improve this library or suggest new features, feel free to fork the repository and submit a pull request.
Clone the repository:
git clone <https://github.com/Arsynth/json_deref.git>
Create a feature branch:
git checkout -b feature/my-new-feature
Submit your changes.
License
json_deref is licensed under the Apache-2.0 License.
Feel free to use, modify, and distribute the library in accordance with the terms of the license.