1+ //! # JSON2RDF Converter Library
2+ //!
3+ //! This library provides functionality for converting JSON data into RDF format.
4+ //! It uses `serde_json` for JSON parsing and `oxrdf` to build and manage RDF graphs.
5+ //!
6+ //! ## Overview
7+ //! - Converts JSON data structures into RDF triples, generating a graph representation.
8+ //! - Supports blank nodes for nested structures and maps JSON properties to RDF predicates.
9+ //!
10+ //! ## Features
11+ //! - Handles JSON Objects, Arrays, Booleans, Numbers, and Strings as RDF triples.
12+ //! - Allows specifying a custom RDF namespace for generated predicates and objects.
13+ //! - Outputs the RDF data to a specified file or prints it to the console.
14+
115use oxrdf:: vocab:: xsd;
216use oxrdf:: { BlankNode , Graph , Literal , NamedNodeRef , TripleRef } ;
317
@@ -6,7 +20,34 @@ use std::collections::VecDeque;
620use std:: fs:: File ;
721use std:: io:: { BufReader , Write } ;
822
9- pub fn json_to_rdf ( file_path : & String , namespace : & Option < String > , output_file : & Option < String > ) {
23+ pub enum GraphOrMessage {
24+ Graph ( Graph ) ,
25+ Message ( String ) ,
26+ }
27+
28+ /// Converts JSON data to RDF format.
29+ ///
30+ /// This function reads JSON data from the specified file, processes it into RDF triples,
31+ /// and outputs the RDF graph. Users can specify a namespace to use for RDF predicates and
32+ /// an output file for saving the generated RDF data.
33+ ///
34+ /// # Arguments
35+ /// - `file_path`: Path to the JSON file.
36+ /// - `namespace`: Optional custom namespace for RDF predicates.
37+ /// - `output_file`: Optional output file path for writing RDF data.
38+ ///
39+ /// # Example
40+ /// ```rust
41+ /// use json2rdf::json_to_rdf;
42+ ///
43+ /// json_to_rdf(&"test/airplane.json".to_string(), &Some("http://example.com/ns#".to_string()), &Some("output.nt".to_string()));
44+ /// ```
45+
46+ pub fn json_to_rdf (
47+ file_path : & String ,
48+ namespace : & Option < String > ,
49+ output_file : & Option < String > ,
50+ ) -> Result < GraphOrMessage , String > {
1051 let rdf_namespace: String = if namespace. is_some ( ) {
1152 namespace. clone ( ) . unwrap ( )
1253 } else {
@@ -67,13 +108,44 @@ pub fn json_to_rdf(file_path: &String, namespace: &Option<String>, output_file:
67108 }
68109 }
69110
70- let mut buffer: Vec < u8 > = Vec :: new ( ) ;
71- writeln ! ( buffer, "{}" , graph. to_string( ) ) . unwrap ( ) ;
72-
73- let file = File :: create ( "foo.txt" ) ;
74- writeln ! ( file. unwrap( ) , "{}" , String :: from_utf8_lossy( & buffer) ) . unwrap ( ) ;
111+ if let Some ( output_path) = output_file {
112+ let mut file = File :: create ( output_path) . expect ( "Error creating file" ) ;
113+ writeln ! ( file, "{}" , graph) . expect ( "Error writing to file" ) ;
114+ Ok ( GraphOrMessage :: Message ( format ! (
115+ "RDF created at: {}" ,
116+ output_path
117+ ) ) )
118+ } else {
119+ Ok ( GraphOrMessage :: Graph ( graph) )
120+ }
75121}
76122
123+ /// This function handles different JSON data types, converting each into RDF triples:
124+ /// - JSON Objects create new blank nodes and recursively process nested values.
125+ /// - JSON Arrays iterate over each element and process it as an individual value.
126+ /// - JSON Booleans, Numbers, and Strings are converted to RDF literals.
127+ ///
128+ /// # Recursion for Nested Structures
129+ /// Recursion is used to handle deeply nested JSON structures, which may contain multiple
130+ /// levels of objects or arrays. This recursive approach allows the function to "dive" into
131+ /// each nested layer of a JSON structure, creating blank nodes for sub-objects and handling
132+ /// them as new subjects within the RDF graph. As a result, each level of JSON data is
133+ /// systematically transformed into RDF triples, regardless of complexity or depth.
134+ ///
135+ /// # Arguments
136+ /// - `subject_stack`: Stack of blank nodes representing subjects. Each nested level pushes a new subject to the stack.
137+ /// - `property`: RDF predicate (property) associated with the JSON value.
138+ /// - `value`: JSON value to process.
139+ /// - `graph`: RDF graph where triples are added.
140+ /// - `namespace`: Namespace for generating predicate URIs.
141+ ///
142+ /// # JSON Type to RDF Conversion
143+ /// - **Object**: Creates a blank node and recursively processes key-value pairs.
144+ /// - **Array**: Iterates over elements and processes each as a separate value.
145+ /// - **String**: Converts to `xsd:string` literal.
146+ /// - **Boolean**: Converts to `xsd:boolean` literal.
147+ /// - **Number**: Converts to `xsd:int` or `xsd:float` literal based on value type.
148+
77149fn process_value (
78150 subject_stack : & mut VecDeque < BlankNode > ,
79151 property : & Option < String > ,
0 commit comments