Skip to main content

hedl_json/
lib.rs

1// Dweve HEDL - Hierarchical Entity Data Language
2//
3// Copyright (c) 2025 Dweve IP B.V. and individual contributors.
4//
5// SPDX-License-Identifier: Apache-2.0
6//
7// Licensed under the Apache License, Version 2.0 (the "License");
8// you may not use this file except in compliance with the License.
9// You may obtain a copy of the License in the LICENSE file at the
10// root of this repository or at: http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! HEDL JSON Conversion
19//!
20//! Provides bidirectional conversion between HEDL documents and JSON.
21//!
22//! # Features
23//!
24//! - **Bidirectional Conversion**: HEDL ↔ JSON with full fidelity
25//! - **`JSONPath` Queries**: Extract data using standard `JSONPath` expressions
26//! - **JSON Schema Generation**: Generate JSON Schema Draft 7 from HEDL documents
27//! - **Partial Parsing**: Continue parsing despite errors and collect all errors
28//! - **Streaming Support**: Memory-efficient processing of large files
29//! - **JSONL Support**: Newline-delimited JSON for logs and streaming
30//! - **Zero-Copy Optimization**: Reduced allocations for better performance
31//! - **Security Limits**: Configurable limits to prevent `DoS` attacks
32//!
33//! # Modules
34//!
35//! - [`jsonpath`]: `JSONPath` query engine for extracting specific data
36//! - [`schema_gen`]: JSON Schema generation from HEDL documents
37//! - [`streaming`]: Streaming parsers for large files and JSONL format
38//!
39//! # Examples
40//!
41//! ## Basic Conversion
42//!
43//! ```rust
44//! use hedl_json::{json_to_hedl, hedl_to_json};
45//!
46//! let json = r#"{"name": "Alice", "age": 30}"#;
47//! let doc = json_to_hedl(json).unwrap();
48//! let json_out = hedl_to_json(&doc).unwrap();
49//! ```
50//!
51//! ## `JSONPath` Queries
52//!
53//! ```rust
54//! use hedl_json::jsonpath::{query, QueryConfig};
55//!
56//! # fn example() -> Result<(), Box<dyn std::error::Error>> {
57//! let doc = hedl_core::parse(b"name: \"Alice\"\nage: 30")?;
58//! let config = QueryConfig::default();
59//!
60//! // Extract specific fields
61//! let results = query(&doc, "$.name", &config)?;
62//! assert_eq!(results[0].as_str(), Some("Alice"));
63//! # Ok(())
64//! # }
65//! ```
66//!
67//! ## JSON Schema Generation
68//!
69//! ```rust
70//! use hedl_json::schema_gen::{generate_schema, SchemaConfig};
71//!
72//! # fn example() -> Result<(), Box<dyn std::error::Error>> {
73//! let doc = hedl_core::parse(b"name: \"Alice\"\nage: 30")?;
74//! let config = SchemaConfig::builder()
75//!     .title("User Schema")
76//!     .strict(true)
77//!     .build();
78//!
79//! let schema = generate_schema(&doc, &config)?;
80//! // schema is a valid JSON Schema Draft 7 document
81//! # Ok(())
82//! # }
83//! ```
84//!
85//! ## Streaming Large Files
86//!
87//! ```rust
88//! use hedl_json::streaming::{JsonLinesStreamer, StreamConfig};
89//! use std::io::Cursor;
90//!
91//! let jsonl = "{\"id\": \"1\"}\n{\"id\": \"2\"}";
92//! let reader = Cursor::new(jsonl.as_bytes());
93//! let config = StreamConfig::default();
94//!
95//! for result in JsonLinesStreamer::new(reader, config) {
96//!     let doc = result.unwrap();
97//!     // Process each document incrementally
98//! }
99//! ```
100//!
101//! ## Partial Parsing with Error Recovery
102//!
103//! ```rust
104//! use hedl_json::{partial_parse_json, PartialConfig, ErrorTolerance};
105//!
106//! let json = r#"{
107//!     "valid": "data",
108//!     "users": [
109//!         {"id": "1", "name": "Alice"},
110//!         {"id": "2", "name": "Bob"}
111//!     ]
112//! }"#;
113//!
114//! let config = PartialConfig::builder()
115//!     .tolerance(ErrorTolerance::CollectAll)
116//!     .build();
117//!
118//! let result = partial_parse_json(json, &config);
119//!
120//! // Check if parsing completed successfully
121//! if result.is_complete() {
122//!     let doc = result.document.unwrap();
123//!     // Use the document
124//! } else {
125//!     // Handle errors
126//!     for error in &result.errors {
127//!         eprintln!("Error at {}: {}", error.location.path, error.error);
128//!     }
129//!     // Use partial results if available
130//!     if let Some(doc) = result.document {
131//!         // Process what was successfully parsed
132//!     }
133//! }
134//! ```
135//!
136#![cfg_attr(not(test), warn(missing_docs))]
137mod from_json;
138/// JSONPath query engine for extracting specific data.
139pub mod jsonpath;
140/// Schema caching.
141pub mod schema_cache;
142/// JSON Schema generation from HEDL documents.
143pub mod schema_gen;
144/// Streaming JSON conversion.
145pub mod streaming;
146/// String interning and caching.
147pub mod string_cache;
148mod to_json;
149
150#[cfg(feature = "validation")]
151/// JSON schema validation.
152pub mod validation;
153
154// Re-export the shared DEFAULT_SCHEMA from hedl-core for internal use
155pub(crate) use hedl_core::convert::DEFAULT_SCHEMA;
156
157pub use from_json::{
158    from_json,
159    from_json_value,
160    from_json_value_owned,
161    // Partial parsing exports
162    partial_parse_json,
163    partial_parse_json_value,
164    ErrorLocation,
165    ErrorTolerance,
166    FromJsonConfig,
167    FromJsonConfigBuilder,
168    JsonConversionError,
169    ParseError,
170    PartialConfig,
171    PartialConfigBuilder,
172    PartialResult,
173    SurrogatePolicy,
174    DEFAULT_MAX_ARRAY_SIZE,
175    DEFAULT_MAX_DEPTH,
176    DEFAULT_MAX_OBJECT_SIZE,
177    DEFAULT_MAX_STRING_LENGTH,
178};
179pub use to_json::{to_json, to_json_value, ToJsonConfig};
180
181use hedl_core::Document;
182
183/// Convert HEDL document to JSON string
184pub fn hedl_to_json(doc: &Document) -> Result<String, String> {
185    to_json(doc, &ToJsonConfig::default())
186}
187
188/// Convert JSON string to HEDL document
189pub fn json_to_hedl(json: &str) -> Result<Document, String> {
190    from_json(json, &FromJsonConfig::default()).map_err(|e| e.to_string())
191}